mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 01:58:20 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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'
|
||||
@@ -256,7 +256,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 +284,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 # │
|
||||
|
||||
@@ -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 \
|
||||
|
||||
+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)) \
|
||||
|
||||
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 \
|
||||
|
||||
@@ -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_
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
// -*- 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/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,221 @@
|
||||
// -*- 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/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_
|
||||
@@ -0,0 +1,172 @@
|
||||
#ifndef CTL_MOVE_ITERATOR_H_
|
||||
#define CTL_MOVE_ITERATOR_H_
|
||||
#include "iterator_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Iterator>
|
||||
class move_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_type = Iterator;
|
||||
using iterator_category =
|
||||
typename ctl::iterator_traits<Iterator>::iterator_category;
|
||||
using value_type = typename ctl::iterator_traits<Iterator>::value_type;
|
||||
using difference_type =
|
||||
typename ctl::iterator_traits<Iterator>::difference_type;
|
||||
using pointer = Iterator;
|
||||
using reference = value_type&&;
|
||||
|
||||
constexpr move_iterator() : current()
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr move_iterator(Iterator i) : current(i)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
constexpr move_iterator(const move_iterator<U>& u) : current(u.base())
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Iterator base() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
constexpr reference operator*() const
|
||||
{
|
||||
return static_cast<reference>(*current);
|
||||
}
|
||||
|
||||
constexpr pointer operator->() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator++()
|
||||
{
|
||||
++current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator++(int)
|
||||
{
|
||||
move_iterator tmp = *this;
|
||||
++current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator--()
|
||||
{
|
||||
--current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator--(int)
|
||||
{
|
||||
move_iterator tmp = *this;
|
||||
--current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator+(difference_type n) const
|
||||
{
|
||||
return move_iterator(current + n);
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator+=(difference_type n)
|
||||
{
|
||||
current += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator-(difference_type n) const
|
||||
{
|
||||
return move_iterator(current - n);
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator-=(difference_type n)
|
||||
{
|
||||
current -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reference operator[](difference_type n) const
|
||||
{
|
||||
return ctl::move(current[n]);
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator current;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
__attribute__((__always_inline__)) constexpr move_iterator<Iterator>
|
||||
make_move_iterator(Iterator i)
|
||||
{
|
||||
return move_iterator<Iterator>(i);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator==(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return x.base() == y.base();
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator!=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return x.base() < y.base();
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
constexpr move_iterator<Iterator>
|
||||
operator+(typename move_iterator<Iterator>::difference_type n,
|
||||
const move_iterator<Iterator>& x)
|
||||
{
|
||||
return x + n;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr auto
|
||||
operator-(const move_iterator<Iterator1>& x,
|
||||
const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base())
|
||||
{
|
||||
return x.base() - y.base();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MOVE_ITERATOR_H_
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// -*-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_MUTEX_H_
|
||||
#define CTL_MUTEX_H_
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class mutex
|
||||
{
|
||||
public:
|
||||
mutex()
|
||||
{
|
||||
if (pthread_mutex_init(&m_, nullptr))
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
~mutex()
|
||||
{
|
||||
if (pthread_mutex_destroy(&m_))
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (pthread_mutex_lock(&m_))
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
return pthread_mutex_trylock(&m_) == 0;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (pthread_mutex_unlock(&m_))
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
// Delete copy constructor and assignment operator
|
||||
mutex(const mutex&) = delete;
|
||||
mutex& operator=(const mutex&) = delete;
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MUTEX_H_
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
// -*- 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 "new.h"
|
||||
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
static void*
|
||||
_ctl_alloc(size_t n, size_t a) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = memalign(a, n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc_nothrow(size_t n, size_t a, const ctl::nothrow_t&)
|
||||
{
|
||||
void* p;
|
||||
if (!(p = memalign(a, n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc1(size_t n) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = malloc(n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc1_nothrow(size_t n, const ctl::nothrow_t&) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = malloc(n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_ret(size_t, void* p) noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_free(void* p) noexcept
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_nop(void*, void*) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
||||
#undef __weak_reference
|
||||
#define __weak_reference(P, A) P __attribute__((weak, alias(#A)))
|
||||
|
||||
/* The ISO says that these should be replaceable by user code. It also says
|
||||
that the declarations for the first four (i.e. non placement-) operators
|
||||
new are implicitly available in each translation unit, including the std
|
||||
align_val_t parameter. (?) However, <new> also _defines_ the align_val_t
|
||||
type so you can’t just write your own. Our way through this morass is to
|
||||
supply ours as ctl::align_val_t and not implicitly declare anything, for
|
||||
now. If you have any brain cells left after reading this comment then go
|
||||
look at the eight operator delete weak references to free in the below. */
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t,
|
||||
ctl::align_val_t,
|
||||
const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t,
|
||||
ctl::align_val_t,
|
||||
const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t, const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc1_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t, const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc1_nothrow);
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
__weak_reference(void* operator new(size_t, void*) noexcept, _ctl_ret);
|
||||
__weak_reference(void* operator new[](size_t, void*) noexcept, _ctl_ret);
|
||||
|
||||
__weak_reference(void operator delete(void*) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete[](void*) noexcept, _ctl_free);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattribute-alias="
|
||||
__weak_reference(void operator delete(void*, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete[](void*, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete(void*, size_t) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete[](void*, size_t) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete(void*, size_t, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete[](void*, size_t, ctl::align_val_t)
|
||||
noexcept, _ctl_free);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
__weak_reference(void operator delete(void*, void*) noexcept, _ctl_nop);
|
||||
__weak_reference(void operator delete[](void*, void*) noexcept, _ctl_nop);
|
||||
@@ -0,0 +1,50 @@
|
||||
// -*-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_NEW_H_
|
||||
#define COSMOPOLITAN_CTL_NEW_H_
|
||||
|
||||
#ifndef TINY
|
||||
__static_yoink("__demangle");
|
||||
#endif
|
||||
|
||||
namespace ctl {
|
||||
|
||||
enum class align_val_t : size_t
|
||||
{
|
||||
};
|
||||
|
||||
struct nothrow_t
|
||||
{
|
||||
explicit nothrow_t() = default;
|
||||
};
|
||||
|
||||
inline constexpr nothrow_t nothrow{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
void* operator new(size_t);
|
||||
void* operator new(size_t, const ctl::nothrow_t&) noexcept;
|
||||
void* operator new(size_t, ctl::align_val_t);
|
||||
void* operator new(size_t, ctl::align_val_t, const ctl::nothrow_t&) noexcept;
|
||||
|
||||
void* operator new[](size_t);
|
||||
void* operator new[](size_t, const ctl::nothrow_t&) noexcept;
|
||||
void* operator new[](size_t, ctl::align_val_t);
|
||||
void* operator new[](size_t, ctl::align_val_t, const ctl::nothrow_t&) noexcept;
|
||||
|
||||
void* operator new(size_t, void*) noexcept;
|
||||
void* operator new[](size_t, void*) noexcept;
|
||||
|
||||
void operator delete(void*) noexcept;
|
||||
void operator delete[](void*) noexcept;
|
||||
void operator delete(void*, ctl::align_val_t) noexcept;
|
||||
void operator delete[](void*, ctl::align_val_t) noexcept;
|
||||
void operator delete(void*, size_t) noexcept;
|
||||
void operator delete[](void*, size_t) noexcept;
|
||||
void operator delete(void*, size_t, ctl::align_val_t) noexcept;
|
||||
void operator delete[](void*, size_t, ctl::align_val_t) noexcept;
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_NEW_H_
|
||||
@@ -0,0 +1,123 @@
|
||||
// -*-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_NUMERIC_LIMITS_H_
|
||||
#define CTL_NUMERIC_LIMITS_H_
|
||||
#include "is_integral.h"
|
||||
#include "is_unsigned.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class numeric_limits
|
||||
{
|
||||
static constexpr T max_signed()
|
||||
{
|
||||
return T(((uintmax_t)1 << (sizeof(T) * 8 - 1)) - 1);
|
||||
}
|
||||
|
||||
static constexpr T max_unsigned()
|
||||
{
|
||||
return T(~T(0));
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr bool is_specialized = ctl::is_integral<T>::value;
|
||||
static constexpr bool is_signed = !ctl::is_unsigned<T>::value;
|
||||
static constexpr bool is_integer = ctl::is_integral<T>::value;
|
||||
static constexpr bool is_exact = ctl::is_integral<T>::value;
|
||||
static constexpr int digits = sizeof(T) * 8 - (is_signed ? 1 : 0);
|
||||
|
||||
static constexpr T min() noexcept
|
||||
{
|
||||
return is_signed ? T(-max_signed() - 1) : T(0);
|
||||
}
|
||||
|
||||
static constexpr T max() noexcept
|
||||
{
|
||||
return is_signed ? max_signed() : max_unsigned();
|
||||
}
|
||||
|
||||
static constexpr T lowest() noexcept
|
||||
{
|
||||
return min();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<bool>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr int digits = 1;
|
||||
|
||||
static constexpr bool min() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr bool max() noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr bool lowest() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<float>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr int digits = 24;
|
||||
|
||||
static constexpr float min() noexcept
|
||||
{
|
||||
return __FLT_MIN__;
|
||||
}
|
||||
|
||||
static constexpr float max() noexcept
|
||||
{
|
||||
return __FLT_MAX__;
|
||||
}
|
||||
|
||||
static constexpr float lowest() noexcept
|
||||
{
|
||||
return -max();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<double>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr int digits = 53;
|
||||
|
||||
static constexpr double min() noexcept
|
||||
{
|
||||
return __DBL_MIN__;
|
||||
}
|
||||
|
||||
static constexpr double max() noexcept
|
||||
{
|
||||
return __DBL_MAX__;
|
||||
}
|
||||
|
||||
static constexpr double lowest() noexcept
|
||||
{
|
||||
return -max();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_NUMERIC_LIMITS_H_
|
||||
+32
-20
@@ -1,10 +1,9 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
@@ -14,38 +13,45 @@ class optional
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
~optional() = default;
|
||||
~optional()
|
||||
{
|
||||
if (present_)
|
||||
value_.~T();
|
||||
}
|
||||
|
||||
optional() noexcept : present_(false)
|
||||
{
|
||||
}
|
||||
|
||||
optional(const T& value) : present_(true), value_(value)
|
||||
optional(const T& value) : present_(true)
|
||||
{
|
||||
new (&value_) T(value);
|
||||
}
|
||||
|
||||
optional(T&& value) : present_(true), value_(std::move(value))
|
||||
optional(T&& value) : present_(true)
|
||||
{
|
||||
new (&value_) T(ctl::move(value));
|
||||
}
|
||||
|
||||
optional(const optional& other) : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
if (other.present_)
|
||||
new (&value_) T(other.value_);
|
||||
}
|
||||
|
||||
optional(optional&& other) noexcept : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
if (other.present_)
|
||||
new (&value_) T(ctl::move(other.value_));
|
||||
}
|
||||
|
||||
optional& operator=(const optional& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
reset();
|
||||
if (other.present_)
|
||||
new (&value_) T(other.value_);
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = other.value_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -53,9 +59,10 @@ class optional
|
||||
optional& operator=(optional&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
reset();
|
||||
if (other.present_)
|
||||
new (&value_) T(ctl::move(other.value_));
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -78,7 +85,7 @@ class optional
|
||||
{
|
||||
if (!present_)
|
||||
__builtin_trap();
|
||||
return std::move(value_);
|
||||
return ctl::move(value_);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
@@ -102,26 +109,31 @@ class optional
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... args)
|
||||
{
|
||||
reset();
|
||||
present_ = true;
|
||||
value_ = T(std::forward<Args>(args)...);
|
||||
new (&value_) T(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void swap(optional& other) noexcept
|
||||
{
|
||||
using ctl::swap;
|
||||
if (present_ && other.present_) {
|
||||
std::swap(value_, other.value_);
|
||||
swap(value_, other.value_);
|
||||
} else if (present_) {
|
||||
other.emplace(std::move(value_));
|
||||
other.emplace(ctl::move(value_));
|
||||
reset();
|
||||
} else if (other.present_) {
|
||||
emplace(std::move(other.value_));
|
||||
emplace(ctl::move(other.value_));
|
||||
other.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
T value_;
|
||||
};
|
||||
bool present_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
// -*- 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 "ostream.h"
|
||||
#include "dubble.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "string_view.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||
|
||||
ostream cout(stdout);
|
||||
ostream cerr(stderr);
|
||||
|
||||
ostream::~ostream() = default;
|
||||
|
||||
ostream::ostream(FILE* file) : ios(file)
|
||||
{
|
||||
}
|
||||
|
||||
ostream::ostream(ostream&& other) noexcept : ios(other.file_)
|
||||
{
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator=(ostream&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(const char* str)
|
||||
{
|
||||
if (good() && str)
|
||||
if (fputs(str, file_) < 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(char c)
|
||||
{
|
||||
if (good())
|
||||
if (fputc(c, file_) == EOF)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(int n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[12];
|
||||
FormatInt32(buf, n);
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(unsigned n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[12];
|
||||
FormatUint32(buf, n);
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(long n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[21];
|
||||
FormatInt64(buf, n);
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(unsigned long n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[21];
|
||||
FormatUint64(buf, n);
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(float f)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||
kDoubleToPrintfG.ToShortestSingle(f, &b);
|
||||
b.Finalize();
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(double d)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||
kDoubleToPrintfG.ToShortest(d, &b);
|
||||
b.Finalize();
|
||||
if (fputs(buf, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(const string_view& s)
|
||||
{
|
||||
if (good() && s.size())
|
||||
if (!fwrite(s.data(), s.size(), 1, file_))
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(bool b)
|
||||
{
|
||||
if (good()) {
|
||||
const char* value =
|
||||
(flags() & boolalpha) ? (b ? "true" : "false") : (b ? "1" : "0");
|
||||
if (fputs(value, file_) < 0)
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::operator<<(ostream& (*manip)(ostream&))
|
||||
{
|
||||
return manip(*this);
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::put(char c)
|
||||
{
|
||||
if (good())
|
||||
if (fputc(c, file_) == EOF)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::write(const char* s, streamsize n)
|
||||
{
|
||||
if (good())
|
||||
if (fwrite(s, 1, n, file_) != static_cast<size_t>(n))
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
ostream::flush()
|
||||
{
|
||||
if (good())
|
||||
if (fflush(file_) != 0)
|
||||
setstate(badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream&
|
||||
endl(ostream& os)
|
||||
{
|
||||
return os.put('\n').flush();
|
||||
}
|
||||
|
||||
ostream&
|
||||
ends(ostream& os)
|
||||
{
|
||||
return os.put('\0');
|
||||
}
|
||||
|
||||
ostream&
|
||||
flush(ostream& os)
|
||||
{
|
||||
return os.flush();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -0,0 +1,56 @@
|
||||
// -*-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_OSTREAM_H_
|
||||
#define CTL_OSTREAM_H_
|
||||
#include "ios.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string_view;
|
||||
|
||||
class ostream : public ios
|
||||
{
|
||||
public:
|
||||
ostream() = delete;
|
||||
explicit ostream(FILE*);
|
||||
virtual ~ostream();
|
||||
|
||||
ostream& operator<<(const char*);
|
||||
ostream& operator<<(bool);
|
||||
ostream& operator<<(char);
|
||||
ostream& operator<<(int);
|
||||
ostream& operator<<(unsigned);
|
||||
ostream& operator<<(long);
|
||||
ostream& operator<<(unsigned long);
|
||||
ostream& operator<<(float);
|
||||
ostream& operator<<(double);
|
||||
ostream& operator<<(const ctl::string_view&);
|
||||
ostream& operator<<(ostream& (*)(ostream&));
|
||||
|
||||
ostream& put(char);
|
||||
ostream& write(const char*, streamsize);
|
||||
ostream& flush();
|
||||
|
||||
ostream(ostream&&) noexcept;
|
||||
ostream& operator=(ostream&&) noexcept;
|
||||
|
||||
private:
|
||||
ostream(const ostream&) = delete;
|
||||
ostream& operator=(const ostream&) = delete;
|
||||
};
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
|
||||
ostream&
|
||||
endl(ostream&);
|
||||
|
||||
ostream&
|
||||
ends(ostream&);
|
||||
|
||||
ostream&
|
||||
flush(ostream&);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OSTREAM_H_
|
||||
@@ -0,0 +1,150 @@
|
||||
// -*- 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 "ostringstream.h"
|
||||
#include "dubble.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
|
||||
|
||||
ostringstream::ostringstream() : buffer_(), write_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ostringstream::ostringstream(const string_view& str)
|
||||
: buffer_(str), write_pos_(0)
|
||||
{
|
||||
}
|
||||
|
||||
string
|
||||
ostringstream::str() const
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
void
|
||||
ostringstream::str(const string& s)
|
||||
{
|
||||
buffer_ = s;
|
||||
write_pos_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ostringstream::clear()
|
||||
{
|
||||
ios_base::clear();
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(char c)
|
||||
{
|
||||
if (good()) {
|
||||
if (write_pos_ < buffer_.size()) {
|
||||
buffer_[write_pos_++] = c;
|
||||
} else {
|
||||
buffer_.push_back(c);
|
||||
++write_pos_;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(const string_view& s)
|
||||
{
|
||||
if (good()) {
|
||||
if (write_pos_ + s.size() <= buffer_.size()) {
|
||||
buffer_.replace(write_pos_, s.size(), s);
|
||||
} else {
|
||||
buffer_.replace(write_pos_, buffer_.size() - write_pos_, s);
|
||||
buffer_.append(s.substr(buffer_.size() - write_pos_));
|
||||
}
|
||||
write_pos_ += s.size();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(int n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[12];
|
||||
*this << string_view(buf, FormatInt32(buf, n) - buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(unsigned n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[12];
|
||||
*this << string_view(buf, FormatUint32(buf, n) - buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(long n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[21];
|
||||
*this << string_view(buf, FormatInt64(buf, n) - buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(unsigned long n)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[21];
|
||||
*this << string_view(buf, FormatUint64(buf, n) - buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(float f)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||
kDoubleToPrintfG.ToShortestSingle(f, &b);
|
||||
b.Finalize();
|
||||
*this << string_view(buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostringstream&
|
||||
ostringstream::operator<<(double d)
|
||||
{
|
||||
if (good()) {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder b(buf, sizeof(buf));
|
||||
kDoubleToPrintfG.ToShortest(d, &b);
|
||||
b.Finalize();
|
||||
*this << string_view(buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
@@ -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_OSTRINGSTREAM_H_
|
||||
#define CTL_OSTRINGSTREAM_H_
|
||||
#include "ios_base.h"
|
||||
#include "string.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class ostringstream : public ios_base
|
||||
{
|
||||
public:
|
||||
ostringstream();
|
||||
explicit ostringstream(const ctl::string_view&);
|
||||
|
||||
ctl::string str() const;
|
||||
void str(const ctl::string& s);
|
||||
void clear();
|
||||
|
||||
ostringstream& operator<<(char);
|
||||
ostringstream& operator<<(const ctl::string_view&);
|
||||
ostringstream& operator<<(int);
|
||||
ostringstream& operator<<(unsigned int);
|
||||
ostringstream& operator<<(long);
|
||||
ostringstream& operator<<(unsigned long);
|
||||
ostringstream& operator<<(float);
|
||||
ostringstream& operator<<(double);
|
||||
|
||||
private:
|
||||
ctl::string buffer_;
|
||||
size_t write_pos_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OSTRINGSTREAM_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_OUT_OF_RANGE_H_
|
||||
#define CTL_OUT_OF_RANGE_H_
|
||||
#include "exception.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class out_of_range : public ctl::exception
|
||||
{
|
||||
public:
|
||||
out_of_range() noexcept = default;
|
||||
~out_of_range() override = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "ctl::out_of_range";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OUT_OF_RANGE_H_
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// -*-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_PAIR_H_
|
||||
#define CTL_PAIR_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct pair
|
||||
{
|
||||
using first_type = T1;
|
||||
using second_type = T2;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
constexpr pair() : first(), second()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(const T1& x, const T2& y) : first(x), second(y)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(const pair<T1, T2>& p) : first(p.first), second(p.second)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(U1&& x, U2&& y)
|
||||
: first(ctl::forward<U1>(x)), second(ctl::forward<U2>(y))
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(const pair<U1, U2>& p) : first(p.first), second(p.second)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(pair<T1, T2>&& p)
|
||||
: first(ctl::move(p.first)), second(ctl::move(p.second))
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(pair<U1, U2>&& p)
|
||||
: first(ctl::move(p.first)), second(ctl::move(p.second))
|
||||
{
|
||||
}
|
||||
|
||||
pair& operator=(const pair& other)
|
||||
{
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
pair& operator=(pair&& other) noexcept
|
||||
{
|
||||
first = ctl::move(other.first);
|
||||
second = ctl::move(other.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
pair& operator=(const pair<U1, U2>& other)
|
||||
{
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
pair& operator=(pair<U1, U2>&& other)
|
||||
{
|
||||
first = ctl::move(other.first);
|
||||
second = ctl::move(other.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(pair& other) noexcept
|
||||
{
|
||||
using ctl::swap;
|
||||
swap(first, other.first);
|
||||
swap(second, other.second);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr pair<T1, T2>
|
||||
make_pair(T1&& t, T2&& u)
|
||||
{
|
||||
return pair<T1, T2>(ctl::forward<T1>(t), ctl::forward<T2>(u));
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator==(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator!=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator<(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return lhs.first < rhs.first ||
|
||||
(!(rhs.first < lhs.first) && lhs.second < rhs.second);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator<=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator>(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator>=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
void
|
||||
swap(pair<T1, T2>& lhs, pair<T1, T2>& rhs) noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_PAIR_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_PARTITION_H_
|
||||
#define CTL_PARTITION_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename RandomIt, typename Compare>
|
||||
RandomIt
|
||||
partition(RandomIt first, RandomIt last, Compare comp)
|
||||
{
|
||||
auto pivot = *ctl::move(last - 1);
|
||||
auto i = first - 1;
|
||||
|
||||
for (auto j = first; j < last - 1; ++j) {
|
||||
if (comp(*j, pivot)) {
|
||||
++i;
|
||||
ctl::swap(*i, *j);
|
||||
}
|
||||
}
|
||||
|
||||
ctl::swap(*(i + 1), *(last - 1));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_PARTITION_H_
|
||||
@@ -0,0 +1,49 @@
|
||||
// -*-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_REMOVE_CV_H_
|
||||
#define CTL_REMOVE_CV_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
struct remove_const
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_const<const T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_volatile
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_volatile<volatile T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_cv
|
||||
{
|
||||
typedef typename remove_volatile<typename remove_const<T>::type>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
template<class T>
|
||||
using remove_volatile_t = typename remove_volatile<T>::type;
|
||||
|
||||
template<class T>
|
||||
using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_REMOVE_CV_H_
|
||||
@@ -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_REMOVE_EXTENT_H_
|
||||
#define CTL_REMOVE_EXTENT_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct remove_extent
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
struct remove_extent<T[N]>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct remove_extent<T[]>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_extent_t = typename remove_extent<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_REMOVE_EXTENT_H_
|
||||
@@ -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_REMOVE_REFERENCE_H_
|
||||
#define CTL_REMOVE_REFERENCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_REMOVE_REFERENCE_H_
|
||||
Loaded 100 of 1138 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user