mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 17:19:47 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e08a4cd99e | ||
|
|
7ebaff34c6 | ||
|
|
e7be5a5e2b | ||
|
|
30afd6ddbb | ||
|
|
d3167126aa | ||
|
|
d3f87f4c64 | ||
|
|
29ce25c767 | ||
|
|
7996bf67b5 | ||
|
|
626a5d02ee | ||
|
|
527aaa41eb | ||
|
|
421a819d88 | ||
|
|
3374cbba73 | ||
|
|
2018cac11f | ||
|
|
6a5d4ed65b | ||
|
|
493ffc9b7f | ||
|
|
101fb3d9b3 | ||
|
|
f6ba270ff3 | ||
|
|
86d884cce2 | ||
|
|
0ed916ad5c | ||
|
|
1029dcc597 | ||
|
|
c697133a2d | ||
|
|
1ff037df3c | ||
|
|
567d8fe32d | ||
|
|
23dfb79d33 | ||
|
|
76cea6c687 | ||
|
|
63065cdd70 | ||
|
|
3f2a1b696e | ||
|
|
f590e96abd | ||
|
|
f7780de24b | ||
|
|
196942084b | ||
|
|
6be030cd7c | ||
|
|
8c645fa1ee | ||
|
|
3756870635 | ||
|
|
fc65422660 | ||
|
|
01587de761 | ||
|
|
5a9a08d1cf | ||
|
|
bd6d9ff99a | ||
|
|
15ea0524b3 | ||
|
|
fdab49b30e | ||
|
|
135d538b1d | ||
|
|
6dbc3fba18 | ||
|
|
70f77aad33 | ||
|
|
d0cd719375 | ||
|
|
61370983e1 | ||
|
|
72511ff0ac | ||
|
|
c1f8d0678c | ||
|
|
e627bfa359 | ||
|
|
acbabedf27 | ||
|
|
239f8ce76e | ||
|
|
ca4cf67eb8 | ||
|
|
78d3b86ec7 | ||
|
|
44191b3f50 | ||
|
|
e437bed006 | ||
|
|
76957983cf | ||
|
|
387310c659 | ||
|
|
4cb5e21ba8 | ||
|
|
1bf2d8e308 | ||
|
|
98e684622b | ||
|
|
617ddfee93 | ||
|
|
464858dbb4 | ||
|
|
6de12c1032 | ||
|
|
a16eb76f5e | ||
|
|
021c53ba32 | ||
|
|
38921dc46b | ||
|
|
054da021d0 | ||
|
|
199662071a | ||
|
|
572ac7d100 | ||
|
|
d461c6f47d | ||
|
|
67b19ae733 | ||
|
|
c4c812c154 | ||
|
|
388e236360 | ||
|
|
f2c8ddbbe3 | ||
|
|
d1d4388201 | ||
|
|
6ffed14b9c | ||
|
|
7f6d0b8709 | ||
|
|
d7b1919b29 | ||
|
|
f86e6f8eb0 | ||
|
|
7e780e57d4 | ||
|
|
9a5a13854d | ||
|
|
a795017416 | ||
|
|
8e3b361aeb | ||
|
|
f9dd5683a4 | ||
|
|
e38a6e7996 | ||
|
|
ddfaf3fee0 | ||
|
|
0dbf01bf1d | ||
|
|
3a599bfbe1 | ||
|
|
89fc95fefd | ||
|
|
8e37ee2598 | ||
|
|
d9b4f647d8 | ||
|
|
0dde3a0e70 | ||
|
|
32643e9fa7 | ||
|
|
0a92c78035 | ||
|
|
118db71121 | ||
|
|
a0410f0170 | ||
|
|
d44a7dc603 | ||
|
|
2ba6b0158f | ||
|
|
f3effcb703 | ||
|
|
03b476f943 | ||
|
|
8b3e368e9a | ||
|
|
df6b384e31 | ||
|
|
280bdec817 | ||
|
|
2c5e7ec547 | ||
|
|
fdcb8b2f7e | ||
|
|
04c6bc478e | ||
|
|
cc2c1893c5 |
No files matched your search
@@ -1,6 +1,10 @@
|
||||
# Run this command to always ignore formatting commits in git blame
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
|
||||
# Upgraded clang-format to 19.0.0git
|
||||
89fc95fefd40413706ff1bdaac2e8d98b328dbf1
|
||||
# vim c++ filetype in modelines
|
||||
04c6bc478e082263d67c41bedbd033dde2d429eb
|
||||
# Ran clang-format
|
||||
f032b5570b4cd87c6bb4abb54c0b98e69c939955
|
||||
# Applied clang-format update to repo
|
||||
@@ -21,3 +25,5 @@ c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
|
||||
da8baf2aa5ce93b958aca90a0ae69f537806324b
|
||||
# Run clang-format on most sources
|
||||
369f9740de4534c28d0e81ab2afc99decbb9a3e6
|
||||
# Get rid of .internal.h convention in LIBC_INTRIN
|
||||
86d884cce24d773e298a2714c1e3d91ecab9be45
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Low Severity Bugs
|
||||
description: Used to report low severity bugs in cosmopolitan (e.g. cosmetic issues, non critical UI glitches)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "low severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Medium Severity Bug
|
||||
description: Used to report medium severity bugs in cosmopolitan (e.g. Malfunctioning Features but generally still useable)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "medium severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: High Severity Bug
|
||||
description: Used to report high severity bugs in cosmopolitan (e.g. Malfunctioning features hindering important common workflow)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "high severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Critical Severity Bug
|
||||
description: Used to report critical severity bugs in cosmopolitan (e.g. Crashing, Corrupted, Dataloss)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "critical severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Enhancement template
|
||||
description: Used to request enhancements for cosmopolitan
|
||||
title: "Feature Request: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
[Please post your idea first in Discussion if there is not yet a consensus for this enhancement request. This will help to keep this issue tracker focused on enhancements that the community has agreed needs to be implemented.](https://github.com/jart/cosmopolitan/discussions/categories/ideas)
|
||||
|
||||
- type: checkboxes
|
||||
id: prerequisites
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please confirm the following before submitting your enhancement request.
|
||||
options:
|
||||
- label: I am running the latest code. Mention the version if possible as well.
|
||||
required: true
|
||||
- label: I carefully followed the [README.md](https://github.com/jart/cosmopolitan/blob/master/README.md).
|
||||
required: true
|
||||
- label: I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
|
||||
required: true
|
||||
- label: I reviewed the [Discussions](https://github.com/jart/cosmopolitan/discussions), and have a new and useful enhancement to share.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: Please provide a detailed written description of what you were trying to do, and what you expected `cosmopolitan` to do as an enhancement.
|
||||
placeholder: Detailed description of the enhancement
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Please provide a detailed written description of reasons why this feature is necessary and how it is useful to `cosmopolitan` users.
|
||||
placeholder: Explanation of why this feature is needed and its benefits
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: possible-implementation
|
||||
attributes:
|
||||
label: Possible Implementation
|
||||
description: If you have an idea as to how it can be implemented, please write a detailed description. Feel free to give links to external sources or share visuals that might be helpful to understand the details better.
|
||||
placeholder: Detailed description of potential implementation
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,52 @@
|
||||
name: Research
|
||||
description: Track new technical research area
|
||||
title: "Research: "
|
||||
labels: ["research"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Don't forget to check for any [duplicate research issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3A%22research+%F0%9F%94%AC%22)
|
||||
|
||||
- type: checkboxes
|
||||
id: research-stage
|
||||
attributes:
|
||||
label: Research Stage
|
||||
description: Track general state of this research ticket
|
||||
options:
|
||||
- label: Background Research (Let's try to avoid reinventing the wheel)
|
||||
- label: Hypothesis Formed (How do you think this will work and it's effect?)
|
||||
- label: Strategy / Implementation Forming
|
||||
- label: Analysis of results
|
||||
- label: Debrief / Documentation (So people in the future can learn from us)
|
||||
|
||||
- type: textarea
|
||||
id: background
|
||||
attributes:
|
||||
label: Previous existing literature and research
|
||||
description: Whats the current state of the art and whats the motivation for this research?
|
||||
|
||||
- type: textarea
|
||||
id: hypothesis
|
||||
attributes:
|
||||
label: Hypothesis
|
||||
description: How do you think this will work and it's effect?
|
||||
|
||||
- type: textarea
|
||||
id: implementation
|
||||
attributes:
|
||||
label: Implementation
|
||||
description: Got an approach? e.g. a PR ready to go?
|
||||
|
||||
- type: textarea
|
||||
id: analysis
|
||||
attributes:
|
||||
label: Analysis
|
||||
description: How does the proposed implementation behave?
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Refactor (Maintainers)
|
||||
description: Used to track refactoring opportunities
|
||||
title: "Refactor: "
|
||||
labels: ["refactor"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Don't forget to [check for existing refactor issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3Arefactoring) in case it's already covered.
|
||||
Also you may want to check [Pull request refactor label as well](https://github.com/jart/cosmopolitan/pulls?q=is%3Aopen+is%3Apr+label%3Arefactoring) for duplicates too.
|
||||
|
||||
- type: textarea
|
||||
id: background-description
|
||||
attributes:
|
||||
label: Background Description
|
||||
description: Please provide a detailed written description of the pain points you are trying to solve.
|
||||
placeholder: Detailed description behind your motivation to request refactor
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: possible-approaches
|
||||
attributes:
|
||||
label: Possible Refactor Approaches
|
||||
description: If you have some idea of possible approaches to solve this problem. You may want to make it a todo list.
|
||||
placeholder: Your idea of possible refactoring opportunity/approaches
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,15 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: FAQ
|
||||
url: https://github.com/jart/cosmopolitan/wiki/FAQ
|
||||
about: Is your question a common one? You may want to check here first.
|
||||
- name: Got an idea?
|
||||
url: https://github.com/jart/cosmopolitan/discussions/categories/ideas
|
||||
about: Pop it there. It may then become an enhancement ticket.
|
||||
- name: Got a question?
|
||||
url: https://github.com/jart/cosmopolitan/discussions/categories/q-a
|
||||
about: Ask a question there!
|
||||
- name: Want to contribute?
|
||||
url: https://github.com/jart/cosmopolitan/wiki/contribute
|
||||
about: Head to the contribution guide page of the wiki for areas you can help with
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# https://github.com/actions/labeler
|
||||
|
||||
documentation:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- README.md
|
||||
- LICENSE
|
||||
- CONTRIBUTING.md
|
||||
- libc/README.md
|
||||
- tool/cosmocc/README.md
|
||||
- third_party/getopt/README.txt
|
||||
build:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- build/**
|
||||
- Makefile
|
||||
- '*/*.mk'
|
||||
examples:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: examples/**
|
||||
devops:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- .github/**
|
||||
- .clang-format
|
||||
dsp:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- dsp/**
|
||||
ape:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ape/**
|
||||
libc:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- libc/**
|
||||
net:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- net/**
|
||||
third_party:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- third_party/**
|
||||
tool:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tool/**
|
||||
@@ -0,0 +1,17 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "jart/cosmopolitan"
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
configuration-path: '.github/labeler.yml'
|
||||
@@ -101,19 +101,20 @@ XARGS ?= xargs -P4 -rs8000
|
||||
DOT ?= dot
|
||||
CLANG = clang
|
||||
TMPDIR = o/tmp
|
||||
AR = build/bootstrap/ar
|
||||
CP = build/bootstrap/cp
|
||||
RM = build/bootstrap/rm -f
|
||||
GZIP = build/bootstrap/gzip
|
||||
ECHO = build/bootstrap/echo
|
||||
CHMOD = build/bootstrap/chmod
|
||||
TOUCH = build/bootstrap/touch
|
||||
PKG = build/bootstrap/package
|
||||
MKDEPS = build/bootstrap/mkdeps
|
||||
ZIPOBJ = build/bootstrap/zipobj
|
||||
ZIPCOPY = build/bootstrap/zipcopy
|
||||
PECHECK = build/bootstrap/pecheck
|
||||
FIXUPOBJ = build/bootstrap/fixupobj
|
||||
AR = $(BOOTSTRAP)/ar.ape
|
||||
CP = $(BOOTSTRAP)/cp.ape
|
||||
RM = $(BOOTSTRAP)/rm.ape -f
|
||||
GZIP = $(BOOTSTRAP)/gzip.ape
|
||||
ECHO = $(BOOTSTRAP)/echo.ape
|
||||
CHMOD = $(BOOTSTRAP)/chmod.ape
|
||||
TOUCH = $(BOOTSTRAP)/touch.ape
|
||||
PKG = $(BOOTSTRAP)/package.ape
|
||||
MKDEPS = $(BOOTSTRAP)/mkdeps
|
||||
ZIPOBJ = $(BOOTSTRAP)/zipobj
|
||||
ZIPCOPY = $(BOOTSTRAP)/zipcopy
|
||||
PECHECK = $(BOOTSTRAP)/pecheck
|
||||
FIXUPOBJ = $(BOOTSTRAP)/fixupobj
|
||||
OBJBINCOPY = $(BOOTSTRAP)/objbincopy
|
||||
MKDIR = build/bootstrap/mkdir -p
|
||||
COMPILE = build/bootstrap/compile -V9 -M2048m -P8192 $(QUOTA)
|
||||
|
||||
@@ -149,9 +150,10 @@ export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
COSMOCC = .cosmocc/3.3.5
|
||||
COSMOCC = .cosmocc/3.5.7
|
||||
BOOTSTRAP = $(COSMOCC)/bin
|
||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.5.7 596876951b62ad2530c63afc40edd805d751fcb2416e544d249af04ad00bb4ed)
|
||||
|
||||
AS = $(TOOLCHAIN)as
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
@@ -256,7 +258,6 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
||||
include libc/proc/BUILD.mk # │ You can now use threads
|
||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/zlib/BUILD.mk # │
|
||||
include libc/stdio/BUILD.mk # │
|
||||
include tool/hello/BUILD.mk # │
|
||||
@@ -285,9 +286,10 @@ include third_party/ncurses/BUILD.mk # │
|
||||
include third_party/readline/BUILD.mk # │
|
||||
include third_party/libunwind/BUILD.mk # |
|
||||
include third_party/libcxxabi/BUILD.mk # |
|
||||
include third_party/double-conversion/BUILD.mk # │
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/libcxx/BUILD.mk # │
|
||||
include third_party/openmp/BUILD.mk # │
|
||||
include third_party/double-conversion/BUILD.mk # │
|
||||
include third_party/pcre/BUILD.mk # │
|
||||
include third_party/less/BUILD.mk # │
|
||||
include net/https/BUILD.mk # │
|
||||
@@ -434,6 +436,9 @@ loc: o/$(MODE)/tool/build/summy
|
||||
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
CTL \
|
||||
THIRD_PARTY_DOUBLECONVERSION \
|
||||
THIRD_PARTY_OPENMP \
|
||||
TOOL_ARGS \
|
||||
NET_HTTP \
|
||||
LIBC_SOCK \
|
||||
@@ -443,7 +448,6 @@ COSMOPOLITAN_OBJECTS = \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
THIRD_PARTY_TZ \
|
||||
THIRD_PARTY_OPENMP \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_ZLIB_GZ \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
@@ -454,7 +458,6 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_THREAD \
|
||||
LIBC_PROC \
|
||||
THIRD_PARTY_NSYNC_MEM \
|
||||
CTL \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_DLOPEN \
|
||||
|
||||
+2
-4
@@ -162,7 +162,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
@@ -189,7 +188,6 @@ o/$(MODE)/ape/ape-copy-self.o: \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
@@ -220,10 +218,10 @@ o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -f -o $@ $<
|
||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -f -o $@ $<
|
||||
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
||||
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -fm -o $@ $<
|
||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -fm -o $@ $<
|
||||
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-static \
|
||||
|
||||
+3
-3
@@ -1,6 +1,7 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
ENTRY(_start)
|
||||
@@ -11,7 +12,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", 0x010000000000);
|
||||
. = SEGMENT_START("text-segment", 0x000800000000);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
@@ -285,8 +286,7 @@ SECTIONS {
|
||||
|
||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||
ape_stack_round = -ape_stack_align;
|
||||
ape_stack_prot = PROT_READ | PROT_WRITE;
|
||||
|
||||
_tls_size = _tbss_end - _tdata_start;
|
||||
_tdata_size = _tdata_end - _tdata_start;
|
||||
|
||||
@@ -761,7 +761,7 @@ ape_phdrs:
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.stub ape_stack_align,quad
|
||||
.quad 16
|
||||
|
||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||
.long PT_NOTE
|
||||
|
||||
@@ -588,8 +588,6 @@ ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||
ape_stack_filesz = 0;
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||
ape_stack_round = -ape_stack_align;
|
||||
|
||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||
ape_note_filesz = ape_note_end - ape_note;
|
||||
|
||||
@@ -84,9 +84,10 @@
|
||||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCX_NIBBLE(X) \
|
||||
((((X) & 0xf) > 0x9) ? ((X) & 0xf) + 0x37 : ((X) & 0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCXSTUB(SYM, X) \
|
||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||
@@ -98,12 +99,12 @@
|
||||
*
|
||||
* <p>This allows linker scripts to generate printf commands.
|
||||
*/
|
||||
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
|
||||
#define BCO_OCTET(X) (((X) & 0x7) + 0x30)
|
||||
#define BCOB_UNIT(X) \
|
||||
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
||||
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
|
||||
(BCO_OCTET(((X) & 0xff) >> 6) << 8) | 0x5c)
|
||||
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I) * 8)))
|
||||
#define PFSTUB2(SYM, X) \
|
||||
HIDDEN(SYM = (X)); \
|
||||
PFBYTE(SYM, X, 0); \
|
||||
@@ -132,7 +133,7 @@
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
|
||||
#define BCD_SMEAR(X) ((X) + (X)*10000)
|
||||
#define BCD_SMEAR(X) ((X) + (X) * 10000)
|
||||
#define BCD_LEFT(X) \
|
||||
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
|
||||
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
# Actually Portable Executable Specification v0.1
|
||||
|
||||
Actually Portable Executable (APE) is an executable file format that
|
||||
polyglots the Windows Portable Executable (PE) format with a UNIX Sixth
|
||||
Edition style shell script that doesn't have a shebang. This makes it
|
||||
possible to produce a single file binary that executes on the stock
|
||||
installations of the many OSes and architectures.
|
||||
|
||||
## Supported OSes and Architectures
|
||||
|
||||
- AMD64
|
||||
- Linux
|
||||
- MacOS
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
|
||||
- ARM64
|
||||
- Linux
|
||||
- MacOS
|
||||
- FreeBSD
|
||||
- Windows (non-native)
|
||||
|
||||
## File Header
|
||||
|
||||
APE defines three separate file magics, all of which are 8 characters
|
||||
long. Any file that starts with one of these magic values can be
|
||||
considered an APE program.
|
||||
|
||||
### (1) APE MZ Magic
|
||||
|
||||
- ASCII: `MZqFpD='`
|
||||
- Hex: 4d 5a 71 46 70 44 3d 27
|
||||
|
||||
This is the canonical magic used by almost all APE programs. It enables
|
||||
maximum portability between OSes. When interpreted as a shell script, it
|
||||
is assiging a single quoted string to an unused variable. The shell will
|
||||
then ignore subsequent binary content that's placed inside the string.
|
||||
|
||||
It is strongly recommended that this magic value be immediately followed
|
||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
||||
Zsh impose a binary safety check before handing off files that don't
|
||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
||||
can't contain NUL characters.
|
||||
|
||||
The letters were carefully chosen so as to be valid x86 instructions in
|
||||
all operating modes. This makes it possible to store a BIOS bootloader
|
||||
disk image inside an APE binary. For example, simple CLI programs built
|
||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
||||
treated as a floppy disk image.
|
||||
|
||||
The letters also allow for the possibility of being treated on x86-64 as
|
||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
||||
ignored, and execution simply begins at the beginning of the file,
|
||||
similar to how MS-DOS .COM binaries work.
|
||||
|
||||
The 0x4a relative offset of the magic causes execution to jump into the
|
||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
||||
|
||||
#### Decoded as i8086
|
||||
|
||||
```asm
|
||||
dec %bp
|
||||
pop %dx
|
||||
jno 0x4a
|
||||
jo 0x4a
|
||||
```
|
||||
|
||||
#### Decoded as i386
|
||||
|
||||
```asm
|
||||
push %ebp
|
||||
pop %edx
|
||||
jno 0x4a
|
||||
jo 0x4a
|
||||
```
|
||||
|
||||
#### Decoded as x86-64
|
||||
|
||||
```asm
|
||||
rex.WRB
|
||||
pop %r10
|
||||
jno 0x4a
|
||||
jo 0x4a
|
||||
```
|
||||
|
||||
### (2) APE UNIX-Only Magic
|
||||
|
||||
- ASCII: `jartsr='`
|
||||
- Hex: 6a 61 72 74 73 72 3d 27
|
||||
|
||||
Being a novel executable format that was first published in 2020, the
|
||||
APE file format is less understood by industry tools compared to the PE,
|
||||
ELF, and Mach-O executable file formats, which have been around for
|
||||
decades. For this reason, APE programs that use the MZ magic above can
|
||||
attract attention from Windows AV software, which may be unwanted by
|
||||
developers who aren't interested in targeting the Windows platform.
|
||||
Therefore the `jartsr='` magic is defined which enables the creation of
|
||||
APE binaries that can safely target all non-Windows platforms. Even
|
||||
though this magic is less common, APE interpreters and binfmt-misc
|
||||
installations MUST support this.
|
||||
|
||||
It is strongly recommended that this magic value be immediately followed
|
||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
||||
Zsh impose a binary safety check before handing off files that don't
|
||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
||||
can't contain NUL characters.
|
||||
|
||||
The letters were carefully chosen so as to be valid x86 instructions in
|
||||
all operating modes. This makes it possible to store a BIOS bootloader
|
||||
disk image inside an APE binary. For example, simple CLI programs built
|
||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
||||
treated as a floppy disk image.
|
||||
|
||||
The letters also allow for the possibility of being treated on x86-64 as
|
||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
||||
ignored, and execution simply begins at the beginning of the file,
|
||||
similar to how MS-DOS .COM binaries work.
|
||||
|
||||
The 0x78 relative offset of the magic causes execution to jump into the
|
||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
||||
|
||||
#### Decoded as i8086 / i386 / x86-64
|
||||
|
||||
```asm
|
||||
push $0x61
|
||||
jb 0x78
|
||||
jae 0x78
|
||||
```
|
||||
|
||||
### (3) APE Debug Magic
|
||||
|
||||
- ASCII: `APEDBG='`
|
||||
- Hex: 41 50 45 44 42 47 3d 27
|
||||
|
||||
While APE files must be valid shell scripts, in practice, UNIX systems
|
||||
will oftentimes be configured to provide a faster safer alternative to
|
||||
loading an APE binary through `/bin/sh`. The Linux Kernel can be patched
|
||||
to have execve() recognize the APE format and directly load its embedded
|
||||
ELF header. Linux systems can also use binfmt-misc to recognize APE's MZ
|
||||
and jartsr magic, and pass them to a userspace program named `ape` that
|
||||
acts as an interpreter. In such environments, the need sometimes arises
|
||||
to be able to test that the `/bin/sh` is working correctly, in which
|
||||
case the `APEDBG='` magic is RECOMMENDED.
|
||||
|
||||
APE interpreters, execve() implementations, and binfmt-misc installs
|
||||
MUST ignore this magic. If necessary, steps can be taken to help files
|
||||
with this magic be passed to `/bin/sh` like a normal shebang-less shell
|
||||
script for execution.
|
||||
|
||||
## Embedded ELF Header
|
||||
|
||||
APE binaries MAY embed an ELF header inside them. Unlike conventional
|
||||
executable file formats, this header is not stored at a fixed offset.
|
||||
It's instead encoded as octal escape codes in a shell script `printf`
|
||||
statement. For example:
|
||||
|
||||
```
|
||||
printf '\177ELF\2\1\1\011\0\0\0\0\0\0\0\0\2\0\076\0\1\0\0\0\166\105\100\000\000\000\000\000\060\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\165\312\1\1\100\0\070\0\005\000\0\0\000\000\000\000'
|
||||
```
|
||||
|
||||
This `printf` statement MUST appear in the first 8192 bytes of the APE
|
||||
executable, so as to limit how much of the initial portion of a file an
|
||||
intepreter must load.
|
||||
|
||||
Multiple such `printf` statements MAY appear in hte first 8192 bytes, in
|
||||
order to specify multiple architectures. For example, fat binaries built
|
||||
by the `apelink` program (provided by Cosmo Libc) will have two encoded
|
||||
ELF headers, for amd64 and arm64, each of which point into the proper
|
||||
file offsets for their respective native code. Therefore, kernels and
|
||||
interpreters which load the APE format directly MUST check the
|
||||
`e_machine` field of the `Elf64_Ehdr` that's decoded from the octal
|
||||
codes, before accepting a `printf` shell statement as valid.
|
||||
|
||||
These printf statements MUST always use only unescaped ASCII characters
|
||||
or octal escape codes. These printf statements MUST NOT use space saving
|
||||
escape codes such as `\n`. For example, rather than saying `\n` it would
|
||||
be valid to say `\012` instead. It's also valid to say `\12` but only if
|
||||
the encoded characters that follow aren't an octal digit.
|
||||
|
||||
For example, the following algorithm may be used for parsing octal:
|
||||
|
||||
```c
|
||||
static int ape_parse_octal(const unsigned char page[8192], int i, int *pc)
|
||||
{
|
||||
int c;
|
||||
if ('0' <= page[i] && page[i] <= '7') {
|
||||
c = page[i++] - '0';
|
||||
if ('0' <= page[i] && page[i] <= '7') {
|
||||
c *= 8;
|
||||
c += page[i++] - '0';
|
||||
if ('0' <= page[i] && page[i] <= '7') {
|
||||
c *= 8;
|
||||
c += page[i++] - '0';
|
||||
}
|
||||
}
|
||||
*pc = c;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
```
|
||||
|
||||
APE aware interpreters SHOULD only take `e_machine` into consideration.
|
||||
It is the responsibility of the `_start()` function to detect the OS.
|
||||
Therefore, multiple `printf` statements are only embedded in the shell
|
||||
script for different CPU architectures.
|
||||
|
||||
The OS ABI field of an APE embedded `Elf64_Ehdr` SHOULD be set to
|
||||
`ELFOSABI_FREEBSD`, since it's the only UNIX OS APE supports that
|
||||
actually checks the field. However different values MAY be chosen for
|
||||
binaries that don't intend to have FreeBSD in their support vector.
|
||||
|
||||
Counter-intuitively, the ARM64 ELF header is used on the MacOS ARM64
|
||||
platform when loading from fat binaries.
|
||||
|
||||
## Embedded Mach-O Header (x86-64 only)
|
||||
|
||||
APE shell scripts that support MacOS on AMD64 must use the `dd` command
|
||||
in a very specific way to specify how the embedded binary Macho-O header
|
||||
is copied backward to the start of the file. For example:
|
||||
|
||||
```
|
||||
dd if="$o" of="$o" bs=8 skip=433 count=66 conv=notrunc
|
||||
```
|
||||
|
||||
These `dd` statements have traditionally been generated by the GNU as
|
||||
and ld.bfd programs by encoding ASCII into 64-bit linker relocations,
|
||||
which necessitated a fixed width for integer values. It took several
|
||||
iterations over APE's history before we eventually got it right:
|
||||
|
||||
- `arg=" 9293"` is how we originally had ape do it
|
||||
- `arg=$(( 9293))` b/c busybox sh disliked quoted space
|
||||
- `arg=9293 ` is generated by modern apelink program
|
||||
|
||||
Software that parses the APE file format, which needs to extract to be
|
||||
able extract the Macho-O x86-64 header SHOULD support the old binaries
|
||||
that use the previous encodings. To make backwards compatibility simple
|
||||
the following regular expression may be used, which generalizes to all
|
||||
defined formats:
|
||||
|
||||
```c
|
||||
regcomp(&rx,
|
||||
"bs=" // dd block size arg
|
||||
"(['\"] *)?" // #1 optional quote w/ space
|
||||
"(\\$\\(\\( *)?" // #2 optional math w/ space
|
||||
"([[:digit:]]+)" // #3
|
||||
"( *\\)\\))?" // #4 optional math w/ space
|
||||
"( *['\"])?" // #5 optional quote w/ space
|
||||
" +" //
|
||||
"skip=" // dd skip arg
|
||||
"(['\"] *)?" // #6 optional quote w/ space
|
||||
"(\\$\\(\\( *)?" // #7 optional math w/ space
|
||||
"([[:digit:]]+)" // #8
|
||||
"( *\\)\\))?" // #9 optional math w/ space
|
||||
"( *['\"])?" // #10 optional quote w/ space
|
||||
" +" //
|
||||
"count=" // dd count arg
|
||||
"(['\"] *)?" // #11 optional quote w/ space
|
||||
"(\\$\\(\\( *)?" // #12 optional math w/ space
|
||||
"([[:digit:]]+)", // #13
|
||||
REG_EXTENDED);
|
||||
```
|
||||
|
||||
For further details, see the canonical implementation in
|
||||
`cosmopolitan/tool/build/assimilate.c`.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-24
@@ -127,32 +127,10 @@ TARGET_ARCH ?= -msse3
|
||||
PYFLAGS += -O1
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
#
|
||||
# Safer binaries good for backend production serving.
|
||||
#
|
||||
# - `make MODE=asan`
|
||||
# - Memory safety
|
||||
# - Production worthy
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
#
|
||||
ifeq ($(MODE), asan)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=address
|
||||
TARGET_ARCH ?= -msse3
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
#
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Enables asan
|
||||
# - Enables ubsan
|
||||
# - Stack canaries
|
||||
# - No optimization
|
||||
@@ -161,9 +139,9 @@ endif
|
||||
ifeq ($(MODE), dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
TARGET_ARCH ?= -msse3
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
QUOTA ?= -C64 -L300
|
||||
|
||||
@@ -64,9 +64,6 @@ BACKTRACES = \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! build/bootstrap/echo.com -n; then
|
||||
if ! build/bootstrap/echo -n; then
|
||||
cat <<'EOF' >&2
|
||||
|
||||
ERROR
|
||||
|
||||
@@ -18,7 +18,13 @@ CTL_A_CHECKS = \
|
||||
CTL_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
THIRD_PARTY_DOUBLECONVERSION \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_LIBUNWIND \
|
||||
|
||||
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
@@ -36,6 +42,7 @@ $(CTL_A_OBJS): private \
|
||||
-Walloca-larger-than=4096 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fexceptions \
|
||||
|
||||
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
|
||||
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ This package provides an STL alternative that's designed to:
|
||||
|
||||
This code is experimental and mostly for Justine to save herself from
|
||||
the STL trainwreck. That doesn't mean cosmocc users aren't welcome to
|
||||
use tihs too. You shouldn't expect the design to not change later on.
|
||||
use this too. You shouldn't expect the design to not change later on.
|
||||
|
||||
## Rationale
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ACCUMULATE_H_
|
||||
#define CTL_ACCUMULATE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class T>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = init + *first;
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIt, class T, class BinaryOperation>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = op(init, *first);
|
||||
return init;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ACCUMULATE_H_
|
||||
@@ -0,0 +1,55 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADD_LVALUE_REFERENCE_H_
|
||||
#define CTL_ADD_LVALUE_REFERENCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference<T&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference<T&&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<void>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<const void>
|
||||
{
|
||||
typedef const void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<volatile void>
|
||||
{
|
||||
typedef volatile void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<const volatile void>
|
||||
{
|
||||
typedef const volatile void type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADD_LVALUE_REFERENCE_H_
|
||||
@@ -0,0 +1,43 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADD_POINTER_H_
|
||||
#define CTL_ADD_POINTER_H_
|
||||
#include "remove_reference.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// Primary template
|
||||
template<typename T>
|
||||
struct add_pointer
|
||||
{
|
||||
typedef typename remove_reference<T>::type* type;
|
||||
};
|
||||
|
||||
// Specialization for functions
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Specialization for function references
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R (&)(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Specialization for rvalue references to functions
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R (&&)(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Helper alias template (C++14 and later)
|
||||
template<typename T>
|
||||
using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADD_POINTER_H_
|
||||
@@ -0,0 +1,29 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADDRESSOF_H_
|
||||
#define CTL_ADDRESSOF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T& arg) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char&>(arg)));
|
||||
}
|
||||
|
||||
template<typename R, typename... Args>
|
||||
R (*addressof(R (*&arg)(Args...)) noexcept)
|
||||
(Args...)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T&&) = delete;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADDRESSOF_H_
|
||||
@@ -0,0 +1,24 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADVANCE_H_
|
||||
#define CTL_ADVANCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
constexpr void
|
||||
advance(InputIt& it, Distance n)
|
||||
{
|
||||
while (n > 0) {
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
while (n < 0) {
|
||||
++n;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADVANCE_H_
|
||||
@@ -0,0 +1,20 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALL_OF_H_
|
||||
#define CTL_ALL_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
all_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (!p(*first))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALL_OF_H_
|
||||
@@ -0,0 +1,94 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALLOCATOR_H_
|
||||
#define CTL_ALLOCATOR_H_
|
||||
#include "bad_alloc.h"
|
||||
#include "integral_constant.h"
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class allocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = ctl::true_type;
|
||||
using is_always_equal = ctl::true_type;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
constexpr allocator() noexcept = default;
|
||||
|
||||
constexpr allocator(const allocator&) noexcept = default;
|
||||
|
||||
template<class U>
|
||||
constexpr allocator(const allocator<U>&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ~allocator() = default;
|
||||
|
||||
[[nodiscard]] T* allocate(size_type n)
|
||||
{
|
||||
if (n > __SIZE_MAX__ / sizeof(T))
|
||||
throw ctl::bad_alloc();
|
||||
if (auto p = static_cast<T*>(::operator new(
|
||||
n * sizeof(T), ctl::align_val_t(alignof(T)), ctl::nothrow)))
|
||||
return p;
|
||||
throw ctl::bad_alloc();
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_type n) noexcept
|
||||
{
|
||||
::operator delete(p, n * sizeof(T), ctl::align_val_t(alignof(T)));
|
||||
}
|
||||
|
||||
template<typename U, typename... Args>
|
||||
void construct(U* p, Args&&... args)
|
||||
{
|
||||
::new (static_cast<void*>(p)) U(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void destroy(U* p)
|
||||
{
|
||||
p->~U();
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return __SIZE_MAX__ / sizeof(T);
|
||||
}
|
||||
|
||||
allocator& operator=(const allocator&) = default;
|
||||
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{
|
||||
using other = allocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator==(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator!=(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_H_
|
||||
@@ -0,0 +1,70 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALLOCATOR_TRAITS_H_
|
||||
#define CTL_ALLOCATOR_TRAITS_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Alloc>
|
||||
struct allocator_traits
|
||||
{
|
||||
using allocator_type = Alloc;
|
||||
using value_type = typename Alloc::value_type;
|
||||
using pointer = typename Alloc::value_type*;
|
||||
using const_pointer = const typename Alloc::value_type*;
|
||||
using void_pointer = void*;
|
||||
using const_void_pointer = const void*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using size_type = size_t;
|
||||
|
||||
using propagate_on_container_copy_assignment = ctl::false_type;
|
||||
using propagate_on_container_move_assignment = ctl::true_type;
|
||||
using propagate_on_container_swap = ctl::false_type;
|
||||
using is_always_equal = ctl::true_type;
|
||||
|
||||
template<typename T>
|
||||
struct rebind_alloc
|
||||
{
|
||||
using other = typename Alloc::template rebind<T>::other;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using rebind_traits = allocator_traits<typename rebind_alloc<T>::other>;
|
||||
|
||||
static pointer allocate(Alloc& a, size_type n)
|
||||
{
|
||||
return a.allocate(n);
|
||||
}
|
||||
|
||||
static void deallocate(Alloc& a, pointer p, size_type n)
|
||||
{
|
||||
a.deallocate(p, n);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static void construct(Alloc& a, T* p, Args&&... args)
|
||||
{
|
||||
::new ((void*)p) T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void destroy(Alloc& a, T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
static size_type max_size(const Alloc& a) noexcept
|
||||
{
|
||||
return a.max_size();
|
||||
}
|
||||
|
||||
static Alloc select_on_container_copy_construction(const Alloc& a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_TRAITS_H_
|
||||
@@ -0,0 +1,20 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ANY_OF_H_
|
||||
#define CTL_ANY_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
any_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (p(*first))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ANY_OF_H_
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ARRAY_H_
|
||||
#define CTL_ARRAY_H_
|
||||
#include "initializer_list.h"
|
||||
#include "out_of_range.h"
|
||||
#include "reverse_iterator.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T, size_t N>
|
||||
struct array
|
||||
{
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = const value_type*;
|
||||
using reverse_iterator = ctl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
|
||||
|
||||
T elems[N];
|
||||
|
||||
constexpr array() = default;
|
||||
|
||||
constexpr array(std::initializer_list<T> init)
|
||||
{
|
||||
auto it = init.begin();
|
||||
for (size_t i = 0; i < N && it != init.end(); ++i, ++it)
|
||||
elems[i] = *it;
|
||||
}
|
||||
|
||||
constexpr reference at(size_type pos)
|
||||
{
|
||||
if (pos >= N)
|
||||
throw ctl::out_of_range();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference at(size_type pos) const
|
||||
{
|
||||
if (pos >= N)
|
||||
throw ctl::out_of_range();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type pos)
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference operator[](size_type pos) const
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference front()
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr const_reference front() const
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr reference back()
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr const_reference back() const
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr T* data() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const T* data() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator begin() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator end() noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr const_iterator end() const noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return N == 0;
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
constexpr size_type max_size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
void fill(const T& value)
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
elems[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(array& other) noexcept
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
T temp = elems[i];
|
||||
elems[i] = other.elems[i];
|
||||
other.elems[i] = temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator==(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (!(lhs[i] == rhs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator!=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (lhs[i] < rhs[i])
|
||||
return true;
|
||||
if (rhs[i] < lhs[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void
|
||||
swap(array<T, N>& lhs, array<T, N>& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ARRAY_H_
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BACK_INSERTER_H_
|
||||
#define CTL_BACK_INSERTER_H_
|
||||
#include "iterator.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class Container>
|
||||
class back_insert_iterator
|
||||
{
|
||||
protected:
|
||||
Container* container;
|
||||
|
||||
public:
|
||||
using iterator_category = ctl::output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = void;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
|
||||
explicit back_insert_iterator(Container& c) : container(&c)
|
||||
{
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(const typename Container::value_type& value)
|
||||
{
|
||||
container->push_back(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(typename Container::value_type&& value)
|
||||
{
|
||||
container->push_back(ctl::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator*()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
back_insert_iterator<Container>
|
||||
back_inserter(Container& c)
|
||||
{
|
||||
return back_insert_iterator<Container>(c);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BACK_INSERTER_H_
|
||||
@@ -0,0 +1,23 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BAD_ALLOC_H_
|
||||
#define CTL_BAD_ALLOC_H_
|
||||
#include "exception.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class bad_alloc : public ctl::exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() noexcept = default;
|
||||
~bad_alloc() override = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "ctl::bad_alloc";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BAD_ALLOC_H_
|
||||
@@ -0,0 +1,22 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_CONDITIONAL_H_
|
||||
#define CTL_CONDITIONAL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<bool B, class T, class F>
|
||||
struct conditional
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, class F>
|
||||
struct conditional<false, T, F>
|
||||
{
|
||||
typedef F type;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_CONDITIONAL_H_
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_COPY_H_
|
||||
#define CTL_COPY_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class OutputIt>
|
||||
OutputIt
|
||||
copy(InputIt first, InputIt last, OutputIt d_first)
|
||||
{
|
||||
while (first != last) {
|
||||
*d_first = *first;
|
||||
++d_first;
|
||||
++first;
|
||||
}
|
||||
return d_first;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_COPY_H_
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DECAY_H_
|
||||
#define CTL_DECAY_H_
|
||||
#include "add_pointer.h"
|
||||
#include "conditional.h"
|
||||
#include "is_array.h"
|
||||
#include "is_function.h"
|
||||
#include "remove_cv.h"
|
||||
#include "remove_extent.h"
|
||||
#include "remove_reference.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct decay
|
||||
{
|
||||
private:
|
||||
typedef typename ctl::remove_reference<T>::type U;
|
||||
|
||||
public:
|
||||
typedef typename ctl::conditional<
|
||||
ctl::is_array<U>::value,
|
||||
typename ctl::remove_extent<U>::type*,
|
||||
typename ctl::conditional<ctl::is_function<U>::value,
|
||||
typename ctl::add_pointer<U>::type,
|
||||
typename ctl::remove_cv<U>::type>::type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DECAY_H_
|
||||
@@ -0,0 +1,44 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DEFAULT_DELETE_H_
|
||||
#define CTL_DEFAULT_DELETE_H_
|
||||
#include "enable_if.h"
|
||||
#include "is_convertible.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct default_delete
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U,
|
||||
typename = typename ctl::enable_if<
|
||||
ctl::is_convertible<U*, T*>::value>::type>
|
||||
constexpr default_delete(const default_delete<U>&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U,
|
||||
typename = typename ctl::enable_if<
|
||||
ctl::is_convertible<U (*)[], T (*)[]>::value>::type>
|
||||
constexpr default_delete(const default_delete<U[]>&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete[] p;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DEFAULT_DELETE_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DISTANCE_H_
|
||||
#define CTL_DISTANCE_H_
|
||||
#include "iterator.h"
|
||||
#include "iterator_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIter>
|
||||
constexpr typename ctl::iterator_traits<InputIter>::difference_type
|
||||
distance_impl(InputIter first, InputIter last, input_iterator_tag)
|
||||
{
|
||||
typename ctl::iterator_traits<InputIter>::difference_type res(0);
|
||||
for (; first != last; ++first)
|
||||
++res;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class RandIter>
|
||||
constexpr typename ctl::iterator_traits<RandIter>::difference_type
|
||||
distance_impl(RandIter first, RandIter last, random_access_iterator_tag)
|
||||
{
|
||||
return last - first;
|
||||
}
|
||||
|
||||
template<class InputIter>
|
||||
constexpr typename ctl::iterator_traits<InputIter>::difference_type
|
||||
distance(InputIter first, InputIter last)
|
||||
{
|
||||
return distance_impl(
|
||||
first,
|
||||
last,
|
||||
typename ctl::iterator_traits<InputIter>::iterator_category());
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DISTANCE_H_
|
||||
@@ -0,0 +1,35 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "dubble.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
const double_conversion::DoubleToStringConverter kDoubleToPrintfG(
|
||||
double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
|
||||
double_conversion::DoubleToStringConverter::NO_TRAILING_ZERO,
|
||||
"inf",
|
||||
"nan",
|
||||
'e',
|
||||
-6,
|
||||
10, // let 32-bit ints be represented without exponent
|
||||
6,
|
||||
0,
|
||||
0);
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,13 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_DUBBLE_H_
|
||||
#define COSMOPOLITAN_CTL_DUBBLE_H_
|
||||
#include "third_party/double-conversion/double-to-string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_DUBBLE_H_
|
||||
@@ -0,0 +1,23 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ENABLE_IF_H_
|
||||
#define CTL_ENABLE_IF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<bool B, class T = void>
|
||||
struct enable_if
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct enable_if<true, T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<bool B, class T = void>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ENABLE_IF_H_
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_EQUAL_H_
|
||||
#define CTL_EQUAL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
|
||||
{
|
||||
for (; first1 != last1; ++first1, ++first2) {
|
||||
if (!(*first1 == *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overload that takes a predicate
|
||||
template<class InputIt1, class InputIt2, class BinaryPredicate>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate pred)
|
||||
{
|
||||
for (; first1 != last1; ++first1, ++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overloads that take two ranges (C++14 and later)
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
|
||||
{
|
||||
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
|
||||
if (!(*first1 == *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return first1 == last1 && first2 == last2;
|
||||
}
|
||||
|
||||
template<class InputIt1, class InputIt2, class BinaryPredicate>
|
||||
bool
|
||||
equal(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2,
|
||||
BinaryPredicate pred)
|
||||
{
|
||||
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return first1 == last1 && first2 == last2;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_EQUAL_H_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_EXCEPTION_H_
|
||||
#define CTL_EXCEPTION_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class exception
|
||||
{
|
||||
public:
|
||||
exception() noexcept = default;
|
||||
virtual ~exception() = default;
|
||||
|
||||
virtual const char* what() const noexcept
|
||||
{
|
||||
return "ctl::exception";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_EXCEPTION_H_
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_FILL_H_
|
||||
#define CTL_FILL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename ForwardIt, typename T>
|
||||
void
|
||||
fill(ForwardIt first, ForwardIt last, const T& value)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
*first = value;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_FILL_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_FILL_N_H_
|
||||
#define CTL_FILL_N_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename OutputIt, typename Size, typename T>
|
||||
OutputIt
|
||||
fill_n(OutputIt first, Size count, const T& value)
|
||||
{
|
||||
for (; count > 0; --count, ++first)
|
||||
*first = value;
|
||||
return first;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_FILL_N_H_
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef _LIBCPP_INITIALIZER_LIST
|
||||
#define _LIBCPP_INITIALIZER_LIST
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class T>
|
||||
class initializer_list
|
||||
{
|
||||
constexpr initializer_list(const T* b, size_t s) noexcept
|
||||
: begin_(b), size_(s)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef const T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef const T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
constexpr initializer_list() noexcept : begin_(nullptr), size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
constexpr const T* begin() const noexcept
|
||||
{
|
||||
return begin_;
|
||||
}
|
||||
|
||||
constexpr const T* end() const noexcept
|
||||
{
|
||||
return begin_ + size_;
|
||||
}
|
||||
|
||||
private:
|
||||
const T* begin_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T*
|
||||
begin(initializer_list<T> i) noexcept
|
||||
{
|
||||
return i.begin();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T*
|
||||
end(initializer_list<T> i) noexcept
|
||||
{
|
||||
return i.end();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // _LIBCPP_INITIALIZER_LIST
|
||||
@@ -0,0 +1,31 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_INTEGRAL_CONSTANT_H_
|
||||
#define CTL_INTEGRAL_CONSTANT_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant
|
||||
{
|
||||
static constexpr T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant type;
|
||||
|
||||
constexpr operator value_type() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr value_type operator()() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_INTEGRAL_CONSTANT_H_
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ios::ios(FILE* file) : file_(file)
|
||||
{
|
||||
}
|
||||
|
||||
ios::~ios() = default;
|
||||
|
||||
ios&
|
||||
ios::operator=(ios&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,27 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IOS_H_
|
||||
#define CTL_IOS_H_
|
||||
#include "ios_base.h"
|
||||
|
||||
struct FILE;
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ios : public ios_base
|
||||
{
|
||||
public:
|
||||
explicit ios(FILE*);
|
||||
virtual ~ios();
|
||||
|
||||
protected:
|
||||
ios& operator=(ios&&) noexcept;
|
||||
FILE* file_;
|
||||
|
||||
private:
|
||||
ios(const ios&) = delete;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IOS_H_
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ios_base.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
ios_base::ios_base() : state_(goodbit), flags_(skipws | dec)
|
||||
{
|
||||
}
|
||||
|
||||
ios_base::~ios_base() = default;
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::flags() const
|
||||
{
|
||||
return static_cast<ios_base::fmtflags>(flags_);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::flags(fmtflags fmtfl)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ = fmtfl;
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::setf(fmtflags fmtfl)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ |= fmtfl;
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
ios_base::fmtflags
|
||||
ios_base::setf(fmtflags fmtfl, fmtflags mask)
|
||||
{
|
||||
int old = flags_;
|
||||
flags_ = (flags_ & ~mask) | (fmtfl & mask);
|
||||
return static_cast<ios_base::fmtflags>(old);
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::unsetf(fmtflags mask)
|
||||
{
|
||||
flags_ &= ~mask;
|
||||
}
|
||||
|
||||
ios_base::iostate
|
||||
ios_base::rdstate() const
|
||||
{
|
||||
return static_cast<ios_base::iostate>(state_);
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::clear(int state)
|
||||
{
|
||||
state_ = state;
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::setstate(int state)
|
||||
{
|
||||
state_ |= state;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::good() const
|
||||
{
|
||||
return state_ == goodbit;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::eof() const
|
||||
{
|
||||
return (state_ & eofbit) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::fail() const
|
||||
{
|
||||
return (state_ & (failbit | badbit)) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::bad() const
|
||||
{
|
||||
return (state_ & badbit) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::operator!() const
|
||||
{
|
||||
return fail();
|
||||
}
|
||||
|
||||
ios_base::operator bool() const
|
||||
{
|
||||
return !fail();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,86 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IOS_BASE_H_
|
||||
#define CTL_IOS_BASE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ios_base
|
||||
{
|
||||
public:
|
||||
typedef size_t streamsize;
|
||||
|
||||
enum iostate
|
||||
{
|
||||
goodbit = 0,
|
||||
badbit = 1,
|
||||
failbit = 2,
|
||||
eofbit = 4
|
||||
};
|
||||
|
||||
enum fmtflags
|
||||
{
|
||||
boolalpha = 1 << 0,
|
||||
dec = 1 << 1,
|
||||
fixed = 1 << 2,
|
||||
hex = 1 << 3,
|
||||
internal = 1 << 4,
|
||||
left = 1 << 5,
|
||||
oct = 1 << 6,
|
||||
right = 1 << 7,
|
||||
scientific = 1 << 8,
|
||||
showbase = 1 << 9,
|
||||
showpoint = 1 << 10,
|
||||
showpos = 1 << 11,
|
||||
skipws = 1 << 12,
|
||||
unitbuf = 1 << 13,
|
||||
uppercase = 1 << 14,
|
||||
adjustfield = left | right | internal,
|
||||
basefield = dec | oct | hex,
|
||||
floatfield = scientific | fixed
|
||||
};
|
||||
|
||||
enum openmode
|
||||
{
|
||||
app = 1 << 0,
|
||||
binary = 1 << 1,
|
||||
in = 1 << 2,
|
||||
out = 1 << 3,
|
||||
trunc = 1 << 4,
|
||||
ate = 1 << 5
|
||||
};
|
||||
|
||||
protected:
|
||||
ios_base();
|
||||
virtual ~ios_base();
|
||||
|
||||
int state_;
|
||||
int flags_;
|
||||
|
||||
public:
|
||||
fmtflags flags() const;
|
||||
fmtflags flags(fmtflags);
|
||||
fmtflags setf(fmtflags);
|
||||
fmtflags setf(fmtflags, fmtflags);
|
||||
void unsetf(fmtflags);
|
||||
|
||||
iostate rdstate() const;
|
||||
void clear(int = goodbit);
|
||||
void setstate(int);
|
||||
|
||||
bool good() const;
|
||||
bool eof() const;
|
||||
bool fail() const;
|
||||
bool bad() const;
|
||||
|
||||
bool operator!() const;
|
||||
explicit operator bool() const;
|
||||
|
||||
private:
|
||||
ios_base(const ios_base&) = delete;
|
||||
ios_base& operator=(const ios_base&) = delete;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IOS_BASE_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_ABSTRACT_H_
|
||||
#define CTL_IS_ABSTRACT_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_abstract : public ctl::integral_constant<bool, __is_abstract(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_abstract_v = __is_abstract(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_ABSTRACT_H_
|
||||
@@ -0,0 +1,26 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_ARRAY_H_
|
||||
#define CTL_IS_ARRAY_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_array : ctl::false_type
|
||||
{};
|
||||
|
||||
template<typename T, size_t N>
|
||||
struct is_array<T[N]> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct is_array<T[]> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_array_v = is_array<T>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_ARRAY_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_BASE_OF_H_
|
||||
#define CTL_IS_BASE_OF_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
struct is_base_of
|
||||
: public ctl::integral_constant<bool, __is_base_of(Base, Derived)>
|
||||
{};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
inline constexpr bool is_base_of_v = __is_base_of(Base, Derived);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_BASE_OF_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_CLASS_H_
|
||||
#define CTL_IS_CLASS_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_class : public ctl::integral_constant<bool, __is_class(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_class_v = __is_class(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_CLASS_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_CONSTRUCTIBLE_H_
|
||||
#define CTL_IS_CONSTRUCTIBLE_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class _Tp, class... _Args>
|
||||
struct is_constructible
|
||||
: public ctl::integral_constant<bool, __is_constructible(_Tp, _Args...)>
|
||||
{};
|
||||
|
||||
template<class _Tp, class... _Args>
|
||||
inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_CONSTRUCTIBLE_H_
|
||||
@@ -0,0 +1,53 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_CONVERTIBLE_H_
|
||||
#define CTL_IS_CONVERTIBLE_H_
|
||||
#include "ctl/integral_constant.h"
|
||||
#include "ctl/void_t.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// Declaration of declval
|
||||
template<typename T>
|
||||
T&&
|
||||
declval() noexcept;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename From, typename To, typename = void>
|
||||
struct is_convertible_impl : ctl::false_type
|
||||
{};
|
||||
|
||||
template<typename From, typename To>
|
||||
struct is_convertible_impl<From,
|
||||
To,
|
||||
void_t<decltype(static_cast<To>(declval<From>()))>>
|
||||
: true_type
|
||||
{};
|
||||
|
||||
// Handle void types separately
|
||||
template<>
|
||||
struct is_convertible_impl<void, void> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<typename To>
|
||||
struct is_convertible_impl<void, To> : ctl::false_type
|
||||
{};
|
||||
|
||||
template<typename From>
|
||||
struct is_convertible_impl<From, void> : ctl::false_type
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename From, typename To>
|
||||
struct is_convertible : detail::is_convertible_impl<From, To>
|
||||
{};
|
||||
|
||||
// Helper variable template (C++17 and later)
|
||||
template<typename From, typename To>
|
||||
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_CONVERTIBLE_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_EMPTY_H_
|
||||
#define CTL_IS_EMPTY_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_empty : public ctl::integral_constant<bool, __is_empty(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_empty_v = __is_empty(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_EMPTY_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_ENUM_H_
|
||||
#define CTL_IS_ENUM_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_enum : public ctl::integral_constant<bool, __is_enum(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_enum_v = __is_enum(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_ENUM_H_
|
||||
@@ -0,0 +1,120 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_FUNCTION_H_
|
||||
#define CTL_IS_FUNCTION_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// Primary template
|
||||
template<class>
|
||||
struct is_function : ctl::false_type
|
||||
{};
|
||||
|
||||
// Specializations for various function types
|
||||
|
||||
// Regular functions
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...)> : ctl::true_type
|
||||
{};
|
||||
|
||||
// Functions with cv-qualifiers
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) volatile> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const volatile> : ctl::true_type
|
||||
{};
|
||||
|
||||
// Functions with ref-qualifiers
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...)&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) volatile&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const volatile&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) &&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) volatile&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args...) const volatile&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
// Variadic functions
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...)> : ctl::true_type
|
||||
{};
|
||||
|
||||
// Variadic functions with cv-qualifiers
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) volatile> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const volatile> : ctl::true_type
|
||||
{};
|
||||
|
||||
// Variadic functions with ref-qualifiers
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...)&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) volatile&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const volatile&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) &&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) volatile&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct is_function<Ret(Args..., ...) const volatile&&> : ctl::true_type
|
||||
{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_FUNCTION_H_
|
||||
@@ -0,0 +1,78 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_INTEGRAL_H_
|
||||
#define CTL_IS_INTEGRAL_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_integral : ctl::false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<bool> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<signed char> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned char> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<short> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned short> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<int> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned int> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<long> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned long> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<long long> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned long long> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char16_t> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char32_t> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<wchar_t> : ctl::true_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_INTEGRAL_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_POLYMORPHIC_H_
|
||||
#define CTL_IS_POLYMORPHIC_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_polymorphic : public ctl::integral_constant<bool, __is_polymorphic(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_polymorphic_v = __is_polymorphic(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_POLYMORPHIC_H_
|
||||
@@ -0,0 +1,35 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_REFERENCE_H_
|
||||
#define CTL_IS_REFERENCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// Primary template
|
||||
template<class T>
|
||||
struct is_reference
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
// Specialization for lvalue reference
|
||||
template<class T>
|
||||
struct is_reference<T&>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
// Specialization for rvalue reference
|
||||
template<class T>
|
||||
struct is_reference<T&&>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
// Helper variable template (C++14 and later)
|
||||
template<class T>
|
||||
inline constexpr bool is_reference_v = is_reference<T>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_REFERENCE_H_
|
||||
@@ -0,0 +1,25 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_SAME_H_
|
||||
#define CTL_IS_SAME_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
inline constexpr bool is_same_v = is_same<T, U>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_SAME_H_
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_SIGNED_H_
|
||||
#define CTL_IS_SIGNED_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_signed
|
||||
{
|
||||
static constexpr bool value = T(0) > T(-1);
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_SIGNED_H_
|
||||
@@ -0,0 +1,25 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_SORTED_H_
|
||||
#define CTL_IS_SORTED_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename It, typename Compare>
|
||||
bool
|
||||
is_sorted(It first, It last, Compare comp)
|
||||
{
|
||||
if (first == last)
|
||||
return true;
|
||||
It next = first;
|
||||
while (++next != last) {
|
||||
if (comp(*next, *first))
|
||||
return false;
|
||||
first = next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_SORTED_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_STANDARD_LAYOUT_H_
|
||||
#define CTL_IS_STANDARD_LAYOUT_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_standard_layout
|
||||
: public ctl::integral_constant<bool, __is_standard_layout(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_standard_layout_v = __is_standard_layout(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_STANDARD_LAYOUT_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_TRIVIAL_H_
|
||||
#define CTL_IS_TRIVIAL_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_trivial : public ctl::integral_constant<bool, __is_trivial(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_trivial_v = __is_trivial(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_TRIVIAL_H_
|
||||
@@ -0,0 +1,18 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_UNION_H_
|
||||
#define CTL_IS_UNION_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_union : public ctl::integral_constant<bool, __is_union(T)>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_union_v = __is_union(T);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_UNION_H_
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_UNSIGNED_H_
|
||||
#define CTL_IS_UNSIGNED_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct is_unsigned
|
||||
{
|
||||
static constexpr bool value = T(0) < T(-1);
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_UNSIGNED_H_
|
||||
@@ -0,0 +1,24 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_IS_VOID_H_
|
||||
#define CTL_IS_VOID_H_
|
||||
#include "integral_constant.h"
|
||||
#include "remove_cv.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename>
|
||||
struct is_void_ : public ctl::false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_void_<void> : public ctl::true_type
|
||||
{};
|
||||
|
||||
template<typename _Tp>
|
||||
struct is_void : public is_void_<typename ctl::remove_cv<_Tp>::type>::type
|
||||
{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_IS_VOID_H_
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "istream.h"
|
||||
#include "libc/ctype.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "numeric_limits.h"
|
||||
#include "string.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
istream cin(stdin);
|
||||
|
||||
istream::~istream() = default;
|
||||
|
||||
istream::istream(FILE* file) : ios(file), gcount_(0)
|
||||
{
|
||||
}
|
||||
|
||||
istream::istream(istream&& other) noexcept
|
||||
: ios(other.file_), gcount_(other.gcount_)
|
||||
{
|
||||
other.file_ = nullptr;
|
||||
other.gcount_ = 0;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator=(istream&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
ios::operator=(ctl::move(other));
|
||||
gcount_ = other.gcount_;
|
||||
other.gcount_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(char& c)
|
||||
{
|
||||
gcount_ = 0;
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit | failbit);
|
||||
} else {
|
||||
c = static_cast<char>(ch);
|
||||
gcount_ = 1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(int& n)
|
||||
{
|
||||
if (fscanf(file_, "%d", &n) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(long& n)
|
||||
{
|
||||
if (fscanf(file_, "%ld", &n) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(double& d)
|
||||
{
|
||||
if (fscanf(file_, "%f", &d) != 1)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(ctl::string& s)
|
||||
{
|
||||
char buffer[1024];
|
||||
if (fscanf(file_, "%1023s", buffer) == 1) {
|
||||
s = buffer;
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(bool& b)
|
||||
{
|
||||
char buffer[6];
|
||||
if (fscanf(file_, "%5s", buffer) == 1) {
|
||||
if (strcmp(buffer, "true") == 0 || strcmp(buffer, "1") == 0) {
|
||||
b = true;
|
||||
} else if (strcmp(buffer, "false") == 0 || strcmp(buffer, "0") == 0) {
|
||||
b = false;
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
} else {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::operator>>(istream& (*manip)(istream&))
|
||||
{
|
||||
return manip(*this);
|
||||
}
|
||||
|
||||
int
|
||||
istream::get()
|
||||
{
|
||||
gcount_ = 0;
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
} else {
|
||||
gcount_ = 1;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::get(char& c)
|
||||
{
|
||||
int ch = get();
|
||||
if (ch != EOF)
|
||||
c = static_cast<char>(ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::getline(char* s, streamsize n)
|
||||
{
|
||||
return getline(s, n, '\n');
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::getline(char* s, streamsize n, char delim)
|
||||
{
|
||||
gcount_ = 0;
|
||||
if (n <= 0) {
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
while (gcount_ < n - 1) {
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
break;
|
||||
}
|
||||
if (ch == delim)
|
||||
break;
|
||||
s[gcount_++] = static_cast<char>(ch);
|
||||
}
|
||||
s[gcount_] = '\0';
|
||||
if (gcount_ == 0)
|
||||
setstate(failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::read(char* s, streamsize n)
|
||||
{
|
||||
gcount_ = fread(s, 1, n, file_);
|
||||
if (gcount_ < n) {
|
||||
setstate(eofbit);
|
||||
if (gcount_ == 0)
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream::streamsize
|
||||
istream::gcount() const
|
||||
{
|
||||
return gcount_;
|
||||
}
|
||||
|
||||
int
|
||||
istream::peek()
|
||||
{
|
||||
int ch = fgetc(file_);
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, file_);
|
||||
} else {
|
||||
setstate(eofbit);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
istream&
|
||||
istream::ignore(streamsize n, int delim)
|
||||
{
|
||||
gcount_ = 0;
|
||||
while (gcount_ < n) {
|
||||
int ch = fgetc(file_);
|
||||
if (ch == EOF) {
|
||||
setstate(eofbit);
|
||||
break;
|
||||
}
|
||||
++gcount_;
|
||||
if (ch == delim)
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream&
|
||||
ws(istream& is)
|
||||
{
|
||||
int ch;
|
||||
while ((ch = is.peek()) != EOF && isspace(ch))
|
||||
is.get();
|
||||
return is;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,53 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ISTREAM_H_
|
||||
#define CTL_ISTREAM_H_
|
||||
#include "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string;
|
||||
|
||||
class istream : public ios
|
||||
{
|
||||
public:
|
||||
istream() = delete;
|
||||
explicit istream(FILE*);
|
||||
virtual ~istream();
|
||||
|
||||
istream& operator>>(char&);
|
||||
istream& operator>>(int&);
|
||||
istream& operator>>(long&);
|
||||
istream& operator>>(double&);
|
||||
istream& operator>>(bool&);
|
||||
istream& operator>>(ctl::string&);
|
||||
istream& operator>>(istream& (*)(istream&));
|
||||
|
||||
int get();
|
||||
istream& get(char&);
|
||||
istream& getline(char*, streamsize);
|
||||
istream& getline(char*, streamsize, char);
|
||||
istream& read(char*, streamsize);
|
||||
streamsize gcount() const;
|
||||
|
||||
int peek();
|
||||
istream& ignore(streamsize = 1, int = -1);
|
||||
|
||||
istream(istream&&) noexcept;
|
||||
istream& operator=(istream&&) noexcept;
|
||||
|
||||
private:
|
||||
streamsize gcount_;
|
||||
|
||||
istream(const istream&) = delete;
|
||||
istream& operator=(const istream&) = delete;
|
||||
};
|
||||
|
||||
extern istream cin;
|
||||
|
||||
istream&
|
||||
ws(istream& is);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ISTREAM_H_
|
||||
@@ -0,0 +1,222 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "istringstream.h"
|
||||
#include "libc/ctype.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
istringstream::istringstream() : buffer_(), read_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
istringstream::istringstream(const ctl::string_view& str)
|
||||
: buffer_(str), read_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ctl::string
|
||||
istringstream::str() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
void
|
||||
istringstream::str(const ctl::string& s)
|
||||
{
|
||||
buffer_ = s;
|
||||
read_pos_ = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(char& c)
|
||||
{
|
||||
if (good() && read_pos_ < buffer_.size()) {
|
||||
c = buffer_[read_pos_++];
|
||||
} else {
|
||||
setstate(ios_base::failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(char* s)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
size_t start = read_pos_;
|
||||
while (read_pos_ < buffer_.size() && !isspace(buffer_[read_pos_])) {
|
||||
s[read_pos_ - start] = buffer_[read_pos_];
|
||||
++read_pos_;
|
||||
}
|
||||
s[read_pos_ - start] = '\0';
|
||||
|
||||
if (start == read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else if (read_pos_ == buffer_.size()) {
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(ctl::string& s)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
s.clear();
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
while (read_pos_ < buffer_.size() && !isspace(buffer_[read_pos_])) {
|
||||
s.push_back(buffer_[read_pos_]);
|
||||
++read_pos_;
|
||||
}
|
||||
|
||||
if (s.empty()) {
|
||||
setstate(ios_base::failbit);
|
||||
} else if (read_pos_ == buffer_.size()) {
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
istringstream&
|
||||
istringstream::read_numeric(T& value)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
while (read_pos_ < buffer_.size() && isspace(buffer_[read_pos_]))
|
||||
++read_pos_;
|
||||
|
||||
// size_t start = read_pos_;
|
||||
bool is_negative = false;
|
||||
if (read_pos_ < buffer_.size() &&
|
||||
(buffer_[read_pos_] == '-' || buffer_[read_pos_] == '+')) {
|
||||
is_negative = (buffer_[read_pos_] == '-');
|
||||
++read_pos_;
|
||||
}
|
||||
|
||||
T result = 0;
|
||||
bool valid = false;
|
||||
while (read_pos_ < buffer_.size() && isdigit(buffer_[read_pos_])) {
|
||||
result = result * 10 + (buffer_[read_pos_] - '0');
|
||||
++read_pos_;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
value = is_negative ? -result : result;
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
} else {
|
||||
setstate(ios_base::failbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(short& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned short& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(int& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned int& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(long& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(unsigned long& n)
|
||||
{
|
||||
return read_numeric(n);
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(float& f)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
char* end;
|
||||
f = strtof(buffer_.c_str() + read_pos_, &end);
|
||||
|
||||
if (end == buffer_.c_str() + read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else {
|
||||
read_pos_ = end - buffer_.c_str();
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
istringstream&
|
||||
istringstream::operator>>(double& d)
|
||||
{
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
char* end;
|
||||
d = strtod(buffer_.c_str() + read_pos_, &end);
|
||||
|
||||
if (end == buffer_.c_str() + read_pos_) {
|
||||
setstate(ios_base::failbit);
|
||||
} else {
|
||||
read_pos_ = end - buffer_.c_str();
|
||||
if (read_pos_ == buffer_.size())
|
||||
setstate(ios_base::eofbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,41 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ISTRINGSTREAM_H_
|
||||
#define CTL_ISTRINGSTREAM_H_
|
||||
#include "ios_base.h"
|
||||
#include "string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class istringstream : public ios_base
|
||||
{
|
||||
public:
|
||||
istringstream();
|
||||
explicit istringstream(const ctl::string_view&);
|
||||
|
||||
string str() const;
|
||||
void str(const string&);
|
||||
|
||||
istringstream& operator>>(char&);
|
||||
istringstream& operator>>(char*);
|
||||
istringstream& operator>>(ctl::string&);
|
||||
istringstream& operator>>(short&);
|
||||
istringstream& operator>>(unsigned short&);
|
||||
istringstream& operator>>(int&);
|
||||
istringstream& operator>>(unsigned int&);
|
||||
istringstream& operator>>(long&);
|
||||
istringstream& operator>>(unsigned long&);
|
||||
istringstream& operator>>(float&);
|
||||
istringstream& operator>>(double&);
|
||||
|
||||
private:
|
||||
ctl::string buffer_;
|
||||
size_t read_pos_;
|
||||
|
||||
template<typename T>
|
||||
istringstream& read_numeric(T&);
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ISTRINGSTREAM_H_
|
||||
@@ -0,0 +1,28 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_OUTPUT_ITERATOR_TAG_H_
|
||||
#define CTL_OUTPUT_ITERATOR_TAG_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct input_iterator_tag
|
||||
{};
|
||||
|
||||
struct output_iterator_tag
|
||||
{};
|
||||
|
||||
struct forward_iterator_tag : public input_iterator_tag
|
||||
{};
|
||||
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag
|
||||
{};
|
||||
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag
|
||||
{};
|
||||
|
||||
struct contiguous_iterator_tag : public random_access_iterator_tag
|
||||
{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OUTPUT_ITERATOR_TAG_H_
|
||||
@@ -0,0 +1,42 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ITERATOR_TRAITS_H_
|
||||
#define CTL_ITERATOR_TRAITS_H_
|
||||
#include "iterator.h"
|
||||
#include "utility.h"
|
||||
#include "void_t.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Iterator, typename = void>
|
||||
struct iterator_traits
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct iterator_traits<T*>
|
||||
{
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using iterator_category = ctl::random_access_iterator_tag;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct iterator_traits<Iterator,
|
||||
ctl::void_t<typename Iterator::iterator_category,
|
||||
typename Iterator::value_type,
|
||||
typename Iterator::difference_type,
|
||||
typename Iterator::pointer,
|
||||
typename Iterator::reference>>
|
||||
{
|
||||
using iterator_category = typename Iterator::iterator_category;
|
||||
using value_type = typename Iterator::value_type;
|
||||
using difference_type = typename Iterator::difference_type;
|
||||
using pointer = typename Iterator::pointer;
|
||||
using reference = typename Iterator::reference;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ITERATOR_TRAITS_H_
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_LESS_H_
|
||||
#define CTL_LESS_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T = void>
|
||||
struct less
|
||||
{
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef bool result_type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct less<void>
|
||||
{
|
||||
template<class T, class U>
|
||||
constexpr auto operator()(T&& lhs,
|
||||
U&& rhs) const -> decltype(ctl::forward<T>(lhs) <
|
||||
ctl::forward<U>(rhs))
|
||||
{
|
||||
return ctl::forward<T>(lhs) < ctl::forward<U>(rhs);
|
||||
}
|
||||
|
||||
typedef void is_transparent;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_LESS_H_ */
|
||||
@@ -0,0 +1,43 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_LEXICOGRAPHICAL_COMPARE_H_
|
||||
#define CTL_LEXICOGRAPHICAL_COMPARE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
lexicographical_compare(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2)
|
||||
{
|
||||
for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
|
||||
if (*first1 < *first2)
|
||||
return true;
|
||||
if (*first2 < *first1)
|
||||
return false;
|
||||
}
|
||||
return (first1 == last1) && (first2 != last2);
|
||||
}
|
||||
|
||||
template<class InputIt1, class InputIt2, class Compare>
|
||||
bool
|
||||
lexicographical_compare(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2,
|
||||
Compare comp)
|
||||
{
|
||||
for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
|
||||
if (comp(*first1, *first2))
|
||||
return true;
|
||||
if (comp(*first2, *first1))
|
||||
return false;
|
||||
}
|
||||
return (first1 == last1) && (first2 != last2);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_LEXICOGRAPHICAL_COMPARE_H_ */
|
||||
@@ -0,0 +1,353 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MAP_H_
|
||||
#define CTL_MAP_H_
|
||||
#include "out_of_range.h"
|
||||
#include "set.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Key, typename Value, typename Compare = ctl::less<Key>>
|
||||
class map
|
||||
{
|
||||
class EntryCompare
|
||||
{
|
||||
public:
|
||||
explicit EntryCompare(Compare comp = Compare()) : comp_(comp)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const ctl::pair<const Key, Value>& lhs,
|
||||
const ctl::pair<const Key, Value>& rhs) const
|
||||
{
|
||||
return comp_(lhs.first, rhs.first);
|
||||
}
|
||||
|
||||
private:
|
||||
Compare comp_;
|
||||
};
|
||||
|
||||
ctl::set<ctl::pair<const Key, Value>, EntryCompare> data_;
|
||||
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = Value;
|
||||
using value_type = ctl::pair<const Key, Value>;
|
||||
using size_type = typename ctl::set<value_type, EntryCompare>::size_type;
|
||||
using difference_type =
|
||||
typename ctl::set<value_type, EntryCompare>::difference_type;
|
||||
using key_compare = Compare;
|
||||
using value_compare = EntryCompare;
|
||||
using iterator = typename ctl::set<value_type, EntryCompare>::iterator;
|
||||
using const_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::const_iterator;
|
||||
using reverse_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::reverse_iterator;
|
||||
using const_reverse_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::const_reverse_iterator;
|
||||
|
||||
map() : data_(EntryCompare())
|
||||
{
|
||||
}
|
||||
|
||||
explicit map(const Compare& comp) : data_(EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
map(const map& other) = default;
|
||||
map(map&& other) noexcept = default;
|
||||
map(std::initializer_list<value_type> init, const Compare& comp = Compare())
|
||||
: data_(init, EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename InputIt>
|
||||
map(InputIt first, InputIt last, const Compare& comp = Compare())
|
||||
: data_(first, last, EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
map& operator=(const map& other) = default;
|
||||
map& operator=(map&& other) noexcept = default;
|
||||
map& operator=(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
data_ = ilist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return data_.cbegin();
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data_.cend();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return data_.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return data_.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return data_.crbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept
|
||||
{
|
||||
return data_.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return data_.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return data_.crend();
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return data_.max_size();
|
||||
}
|
||||
|
||||
Value& operator[](const Key& key)
|
||||
{
|
||||
return ((data_.insert(ctl::make_pair(key, Value()))).first)->second;
|
||||
}
|
||||
|
||||
Value& operator[](Key&& key)
|
||||
{
|
||||
return ((data_.insert(ctl::make_pair(ctl::move(key), Value()))).first)
|
||||
->second;
|
||||
}
|
||||
|
||||
Value& at(const Key& key)
|
||||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
throw ctl::out_of_range();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const Value& at(const Key& key) const
|
||||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
throw ctl::out_of_range();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ctl::pair<iterator, bool> insert(const value_type& value)
|
||||
{
|
||||
return data_.insert(value);
|
||||
}
|
||||
|
||||
ctl::pair<iterator, bool> insert(value_type&& value)
|
||||
{
|
||||
return data_.insert(ctl::move(value));
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
ctl::pair<iterator, bool> insert(P&& value)
|
||||
{
|
||||
return data_.insert(value_type(ctl::forward<P>(value)));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value)
|
||||
{
|
||||
return data_.insert(hint, value);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value)
|
||||
{
|
||||
return data_.insert(hint, ctl::move(value));
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
iterator insert(const_iterator hint, P&& value)
|
||||
{
|
||||
return data_.insert(hint, value_type(ctl::forward<P>(value)));
|
||||
}
|
||||
|
||||
template<typename InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
data_.insert(first, last);
|
||||
}
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
data_.insert(ilist);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
ctl::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return data_.emplace(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return data_.emplace_hint(hint, ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator pos)
|
||||
{
|
||||
return data_.erase(pos);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return data_.erase(first, last);
|
||||
}
|
||||
|
||||
size_type erase(const Key& key)
|
||||
{
|
||||
return data_.erase(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
void swap(map& other) noexcept
|
||||
{
|
||||
data_.swap(other.data_);
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
{
|
||||
return data_.find(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const
|
||||
{
|
||||
return data_.find(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
size_type count(const Key& key) const
|
||||
{
|
||||
return data_.count(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
iterator lower_bound(const Key& key)
|
||||
{
|
||||
return data_.lower_bound(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const Key& key) const
|
||||
{
|
||||
return data_.lower_bound(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
iterator upper_bound(const Key& key)
|
||||
{
|
||||
return data_.upper_bound(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const Key& key) const
|
||||
{
|
||||
return data_.upper_bound(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
ctl::pair<iterator, iterator> equal_range(const Key& key)
|
||||
{
|
||||
return data_.equal_range(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
ctl::pair<const_iterator, const_iterator> equal_range(const Key& key) const
|
||||
{
|
||||
return data_.equal_range(ctl::make_pair(key, Value()));
|
||||
}
|
||||
|
||||
key_compare key_comp() const
|
||||
{
|
||||
return data_.value_comp().comp;
|
||||
}
|
||||
|
||||
value_compare value_comp() const
|
||||
{
|
||||
return data_.value_comp();
|
||||
}
|
||||
|
||||
friend bool operator==(const map& lhs, const map& rhs)
|
||||
{
|
||||
return lhs.data_ == rhs.data_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend bool operator<(const map& lhs, const map& rhs)
|
||||
{
|
||||
return lhs.data_ < rhs.data_;
|
||||
}
|
||||
|
||||
friend bool operator<=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
friend bool operator>(const map& lhs, const map& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
friend bool operator>=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
friend void swap(map& lhs, map& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MAP_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MAX_H_
|
||||
#define CTL_MAX_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T&
|
||||
max(const T& a, const T& b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_MAX_H_ */
|
||||
@@ -0,0 +1,17 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MIN_H_
|
||||
#define CTL_MIN_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T&
|
||||
min(const T& a, const T& b)
|
||||
{
|
||||
return b < a ? b : a;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_MIN_H_ */
|
||||
@@ -0,0 +1,20 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MOVE_BACKWARD_H_
|
||||
#define CTL_MOVE_BACKWARD_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename BidirIt1, typename BidirIt2>
|
||||
BidirIt2
|
||||
move_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last)
|
||||
{
|
||||
while (first != last)
|
||||
*(--d_last) = ctl::move(*(--last));
|
||||
return d_last;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MOVE_BACKWARD_H_
|
||||
Loaded 100 of 1330 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user