From 6393e800218a6d26ec392531995f3a112285fea8 Mon Sep 17 00:00:00 2001 From: Sean McGrail <549813+skmcgrail@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:53:03 -0800 Subject: [PATCH] Add x509-limbo patch and reporting tool (#2049) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description of changes: Describe AWS-LC’s current behavior and how your code changes that behavior. If there are no issues this pr is resolving, explain why this change is necessary. ### Call-outs: * The majority of the x509-limbo patch is a 1-1 copy of the code from the [openssl](https://github.com/C2SP/x509-limbo/tree/main/harness/openssl) harness code from that repository. It just has a very limited set of changes to make it compatible with AWS-LC. I'd suggest not wasting your effort into reviewing that code specifically. * The Go reporting tool and patch will be built and tested in this PR, but we won't be producing the report output and capturing it / diffing it with the tool until a follow-up PR. I've mostly broken this up to alleviate a large code review for everyone. * My current intention is to wire this up into a separate CodeBuild project similar to fuzzing. But for now (since that requires CDK work etc), I have wired-up some simple verification of the patching and the reporting tool into the existing ~Linux CodeBuild project~ GitHub Actions CI. This is only temporary. ### Testing: * I've added plenty of testing to the Go program itself for the functionality the CLI tool relies on for how to produce the reports. * Verified the actual CLI commands locally as well. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license. --------- Co-authored-by: Justin W Smith <103147162+justsmth@users.noreply.github.com> --- .github/workflows/actions-ci.yml | 18 + tests/ci/run_x509_limbo.sh | 46 + tests/ci/x509/limbo-report/.gitignore | 1 + tests/ci/x509/limbo-report/Makefile | 15 + tests/ci/x509/limbo-report/annotate.go | 122 + tests/ci/x509/limbo-report/diff.go | 310 + tests/ci/x509/limbo-report/go.mod | 5 + tests/ci/x509/limbo-report/go.sum | 2 + tests/ci/x509/limbo-report/limbo.go | 271 + tests/ci/x509/limbo-report/main.go | 49 + tests/ci/x509/limbo-report/main_test.go | 931 + tests/ci/x509/x509-limbo.patch | 33252 ++++++++++++++++++++++ 12 files changed, 35022 insertions(+) create mode 100755 tests/ci/run_x509_limbo.sh create mode 100644 tests/ci/x509/limbo-report/.gitignore create mode 100644 tests/ci/x509/limbo-report/Makefile create mode 100644 tests/ci/x509/limbo-report/annotate.go create mode 100644 tests/ci/x509/limbo-report/diff.go create mode 100644 tests/ci/x509/limbo-report/go.mod create mode 100644 tests/ci/x509/limbo-report/go.sum create mode 100644 tests/ci/x509/limbo-report/limbo.go create mode 100644 tests/ci/x509/limbo-report/main.go create mode 100644 tests/ci/x509/limbo-report/main_test.go create mode 100644 tests/ci/x509/x509-limbo.patch diff --git a/.github/workflows/actions-ci.yml b/.github/workflows/actions-ci.yml index f124a24dbe..75f58996e5 100644 --- a/.github/workflows/actions-ci.yml +++ b/.github/workflows/actions-ci.yml @@ -591,3 +591,21 @@ jobs: run: | sudo pkg install -y git gmake cmake go ninja tests/ci/run_bsd_tests.sh + # Temporary to test the x509-limbo patch and building of the reporting tool. + # This will move into a separate project in the next PR. But doing this for now to + # cutdown the review size. + x509-limbo-tooling: + if: github.repository_owner == 'aws' + needs: [sanity-test-run] + name: x509-limbo tooling + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + - name: Verify x509-limbo patch and reporting tool + run: | + ./tests/ci/run_x509_limbo.sh diff --git a/tests/ci/run_x509_limbo.sh b/tests/ci/run_x509_limbo.sh new file mode 100755 index 0000000000..02e5c36e68 --- /dev/null +++ b/tests/ci/run_x509_limbo.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 OR ISC + +set -euxo pipefail + +source tests/ci/common_posix_setup.sh + +# For now we will just verify that the patch applies and our reporting to builds and tests successfully +# Subsequent follow-up PRs will wire this up into a new CodeBuild project and handle producing and tracking +# the reports. + +SCRATCH_DIR="${SYS_ROOT}/scratch" +X509_CI_DIR="${SRC_ROOT}/tests/ci/x509" +X509_LIMBO_SRC="${SCRATCH_DIR}/x509-limbo" + +function build_reporting_tool() { + pushd "${X509_CI_DIR}/limbo-report" + make + mv ./limbo-report "${SCRATCH_DIR}/" + popd # "${X509_CI_DIR}/limbo-report" +} + +function clone_and_patch_x509_limbo() { + git clone https://github.com/C2SP/x509-limbo.git "${X509_LIMBO_SRC}" + pushd "${X509_LIMBO_SRC}" + patch -p1 -i "${X509_CI_DIR}/x509-limbo.patch" + popd # "${X509_LIMBO_SRC}" +} + +function run_aws_lc_harness() { + pushd "${X509_LIMBO_SRC}" + AWS_LC_SRC_DIR="${SRC_ROOT}" make test-aws-lc + popd # "${X509_LIMBO_SRC}" +} + +mkdir -p "${SCRATCH_DIR}" +rm -rf "${SCRATCH_DIR:?}"/* +pushd "${SCRATCH_DIR}" + +build_reporting_tool +clone_and_patch_x509_limbo +run_aws_lc_harness + +popd # "${SCRATCH_DIR}" +# rm -rf "${SCRATCH_DIR:?}" diff --git a/tests/ci/x509/limbo-report/.gitignore b/tests/ci/x509/limbo-report/.gitignore new file mode 100644 index 0000000000..0e298c43c8 --- /dev/null +++ b/tests/ci/x509/limbo-report/.gitignore @@ -0,0 +1 @@ +limbo-report diff --git a/tests/ci/x509/limbo-report/Makefile b/tests/ci/x509/limbo-report/Makefile new file mode 100644 index 0000000000..55f2ded146 --- /dev/null +++ b/tests/ci/x509/limbo-report/Makefile @@ -0,0 +1,15 @@ +.PHONY: all build test fmt vet + +all: build vet test + +build: + go build ./... + +test: + go test ./... + +fmt: + go fmt ./... + +vet: + go vet ./... diff --git a/tests/ci/x509/limbo-report/annotate.go b/tests/ci/x509/limbo-report/annotate.go new file mode 100644 index 0000000000..e8ee0ca8f1 --- /dev/null +++ b/tests/ci/x509/limbo-report/annotate.go @@ -0,0 +1,122 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +package main + +import ( + "encoding/csv" + "encoding/json" + "flag" + "fmt" + "io" + "log" + "os" + "sort" +) + +var annotateHelpDoc string = `report annotate [-csv] + +Annotates a standard x509-limbo results file with information from the provided test descriptors. +By default this will write the result back to the process standard output. + +Options: +-csv Write the results to standard output in csv format rather then the default json format +` + +var annotateCommand struct { + formatAsCsv bool +} + +var annotateFlagSet = func() *flag.FlagSet { + fs := flag.NewFlagSet("annotate", flag.ExitOnError) + fs.BoolVar(&annotateCommand.formatAsCsv, "csv", false, "format output as csv rather then the default") + fs.Usage = func() { + fmt.Fprint(fs.Output(), annotateHelpDoc) + } + + return fs +}() + +func runAnnotateCommand(args []string) error { + if err := annotateFlagSet.Parse(args); err != nil { + return err + } + + if len(annotateFlagSet.Args()) != 2 { + return fmt.Errorf("expect two positional arguments") + } + + limbo, err := parseLimboFile(annotateFlagSet.Arg(0)) + if err != nil { + return err + } + + harnessFilePath := annotateFlagSet.Arg(1) + harnessBytes, err := os.ReadFile(harnessFilePath) + if err != nil { + log.Fatalf("failed to read harnessFile(%v): %v", harnessFilePath, err) + } + + var hr HarnessResults + if err := json.Unmarshal(harnessBytes, &hr); err != nil { + log.Fatalf("failed to parse json: %v", err) + } + if err := hr.Annotate(limbo); err != nil { + return err + } + + if annotateCommand.formatAsCsv { + return writeCsvJudgementReport(&hr, os.Stdout) + } + + return writeJsonJudgementReport(&hr, os.Stdout) +} + +func parseLimboFile(filePath string) (limbo *Limbo, err error) { + testCasesBytes, err := os.ReadFile(filePath) + if err != nil { + return limbo, fmt.Errorf("failed to read limbo test cases: %w", err) + } + + var unmarshaled Limbo + + if err := json.Unmarshal(testCasesBytes, &unmarshaled); err != nil { + return limbo, fmt.Errorf("failed to parse json: %w", err) + } + + limbo = &unmarshaled + + return limbo, nil +} + +func writeJsonJudgementReport(hr *HarnessResults, out io.Writer) error { + jsonWriter := json.NewEncoder(out) + jsonWriter.SetIndent("", " ") + + if err := jsonWriter.Encode(hr); err != nil { + return fmt.Errorf("failed to encode harness judgement: %w", err) + } + + return nil +} + +func writeCsvJudgementReport(hr *HarnessResults, out io.Writer) error { + csvWriter := csv.NewWriter(out) + defer csvWriter.Flush() + + csvWriter.Write([]string{"id", "expected", "result", "judgement", "context"}) + + // Normalize The Report for Diffing + var sortedIds []string + for id := range hr.Results { + sortedIds = append(sortedIds, id) + } + sort.Strings(sortedIds) + + for _, id := range sortedIds { + tr := hr.Results[id] + csvWriter.Write([]string{id, string(tr.ExpectedResult), string(tr.ActualResult), string(tr.Judgement), tr.Context}) + } + + return nil +} diff --git a/tests/ci/x509/limbo-report/diff.go b/tests/ci/x509/limbo-report/diff.go new file mode 100644 index 0000000000..6d0226b1db --- /dev/null +++ b/tests/ci/x509/limbo-report/diff.go @@ -0,0 +1,310 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +package main + +import ( + "bufio" + "encoding/json" + "flag" + "fmt" + "io" + "os" + "sort" + "strings" +) + +var diffHelp string = `report diff + +Provides a difference report between and . These files are expected to be in the +default json file format produced by invoking "report annotate". +` + +var diffFlagSet = func() *flag.FlagSet { + fs := flag.NewFlagSet("diff", flag.ExitOnError) + fs.Usage = func() { + fmt.Fprint(fs.Output(), diffHelp) + } + return fs +}() + +func runDiffCommand(args []string) error { + if err := diffFlagSet.Parse(args); err != nil { + return err + } + + if diffFlagSet.NArg() != 2 { + return fmt.Errorf("expected two positional arguments containing paths to files to diff") + } + + leftReportFilePath := diffFlagSet.Arg(0) + rightReportFilePath := diffFlagSet.Arg(1) + + leftReport, err := os.Open(leftReportFilePath) + if err != nil { + return fmt.Errorf("failed to read %s: %w", leftReportFilePath, err) + } + defer leftReport.Close() + + rightReport, err := os.Open(rightReportFilePath) + if err != nil { + return fmt.Errorf("failed to read %s: %w", rightReportFilePath, err) + } + defer rightReport.Close() + + var leftResults, rightResults HarnessResults + + leftDecoder := json.NewDecoder(leftReport) + rightDecoder := json.NewDecoder(rightReport) + + if err := leftDecoder.Decode(&leftResults); err != nil { + return fmt.Errorf("failed to decode left report: %w", err) + } + + if err := rightDecoder.Decode(&rightResults); err != nil { + return fmt.Errorf("failed to decode right report: %w", err) + } + + diff, err := diffReports(&leftResults, &rightResults) + if err != nil { + return err + } + + if err := diff.Render(os.Stdout); err != nil { + return err + } + + if diff.NeedsAttention() { + os.Exit(1) + } + + return nil +} + +func diffReports(left, right *HarnessResults) (diff Diff, err error) { + var sortedLeftIds []string + var sortedRightIds []string + + for id := range left.Results { + sortedLeftIds = append(sortedLeftIds, id) + } + sort.Strings(sortedLeftIds) + + for id := range right.Results { + sortedRightIds = append(sortedRightIds, id) + } + sort.Strings(sortedRightIds) + + exclusiveLeftIds, commonIds, exclusiveRightIds := intersection(sortedLeftIds, sortedRightIds) + + removed := make(map[Judgement][]string) + added := make(map[Judgement][]string) + + for _, id := range exclusiveLeftIds { + tc := left.Results[id] + slice := removed[tc.Judgement] + slice = append(slice, id) + removed[tc.Judgement] = slice + } + + for _, id := range exclusiveRightIds { + tc := right.Results[id] + slice := added[tc.Judgement] + slice = append(slice, id) + added[tc.Judgement] = slice + } + + changed := make(map[Judgement][]ChangedResult) + unchanged := make(map[Judgement][]string) + + for _, id := range commonIds { + leftTc := left.Results[id] + rightTc := right.Results[id] + + if leftTc.Judgement == rightTc.Judgement { + slice := unchanged[rightTc.Judgement] + slice = append(slice, id) + unchanged[rightTc.Judgement] = slice + } else { + slice := changed[rightTc.Judgement] + slice = append(slice, ChangedResult{ + ID: id, + Was: leftTc.Judgement, + }) + changed[rightTc.Judgement] = slice + } + } + + return Diff{ + Removed: removed, + Added: added, + Changed: changed, + Unchanged: unchanged, + }, nil +} + +type ChangedResult struct { + ID string + Was Judgement +} + +type Diff struct { + Removed map[Judgement][]string + + Added map[Judgement][]string + + Changed map[Judgement][]ChangedResult + + Unchanged map[Judgement][]string +} + +func (diff *Diff) TotalAdded() (count int) { + for i := range diff.Added { + count += len(diff.Added[i]) + } + return count +} + +func (diff *Diff) TotalRemoved() (count int) { + for i := range diff.Removed { + count += len(diff.Removed[i]) + } + return count +} + +func (diff *Diff) TotalChanged() (count int) { + for i := range diff.Changed { + count += len(diff.Changed[i]) + } + return count +} + +func (diff *Diff) TotalUnchanged() (count int) { + for i := range diff.Unchanged { + count += len(diff.Unchanged[i]) + } + return count +} + +func (diff *Diff) Total() int { + return diff.TotalAdded() + diff.TotalChanged() + diff.TotalUnchanged() +} + +func (diff *Diff) NeedsAttention() bool { + return len(diff.Added[unexpectedFailureJudgement]) > 0 || len(diff.Added[unexpectedPassJudgement]) > 0 || + len(diff.Changed[unexpectedFailureJudgement]) > 0 || len(diff.Changed[unexpectedPassJudgement]) > 0 +} + +func (diff *Diff) Render(out io.Writer) (err error) { + writer := bufio.NewWriter(out) + defer func() { + closeErr := writer.Flush() + if err == nil { + err = closeErr + } else if closeErr != nil { + err = fmt.Errorf("close err: %v, original error: %w", closeErr, err) + } + }() + + totalAdded := diff.TotalAdded() + totalRemoved := diff.TotalRemoved() + totalChanged := diff.TotalChanged() + + judgements := Judgements() + + var unchangedSummary strings.Builder + for i, judge := range judgements { + unchangedSummary.WriteString(fmt.Sprintf("%s: %d", judge, len(diff.Added[judge])+len(diff.Unchanged[judge])+len(diff.Changed[judge]))) + if i != len(judgements)-1 { + unchangedSummary.WriteString(", ") + } + } + + writer.WriteString(fmt.Sprintf(`%s + +Report Breakdown: + %d added + %d removed + %d changed + %d unchanged + +`, unchangedSummary.String(), totalAdded, totalRemoved, totalChanged, diff.TotalUnchanged())) + + if totalAdded > 0 { + for _, judge := range judgements { + if _, ok := diff.Added[judge]; !ok { + continue + } + writer.WriteString(fmt.Sprintf("Added %s:\n", judge)) + for _, id := range diff.Added[judge] { + writer.WriteString(fmt.Sprintf("\t%s\n", id)) + } + writer.WriteByte('\n') + } + writer.WriteByte('\n') + } + + if totalRemoved > 0 { + for _, judge := range judgements { + if _, ok := diff.Removed[judge]; !ok { + continue + } + writer.WriteString(fmt.Sprintf("Removed %s:\n", judge)) + for _, id := range diff.Removed[judge] { + writer.WriteString(fmt.Sprintf("\t%s\n", id)) + } + writer.WriteByte('\n') + } + writer.WriteByte('\n') + } + + if totalChanged > 0 { + for _, judge := range judgements { + if _, ok := diff.Changed[judge]; !ok { + continue + } + writer.WriteString(fmt.Sprintf("Changed to %s:\n", judge)) + for _, result := range diff.Changed[judge] { + writer.WriteString(fmt.Sprintf("\t%s (previously %s)\n", result.ID, result.Was)) + } + writer.WriteByte('\n') + } + writer.WriteByte('\n') + } + + return nil +} + +// intersection computes the set intersection of two string slice left and right. +// This expect left and right to have already been sorted, and will return `aAndB` sorted. +func intersection(left, right []string) (a, aAndB, b []string) { + aAndBDedupe := make(map[string]struct{}) + + for _, v := range left { + if isInSlice(right, v) { + aAndBDedupe[v] = struct{}{} + } else { + a = append(a, v) + } + } + + for _, v := range right { + if isInSlice(left, v) { + aAndBDedupe[v] = struct{}{} + } else { + b = append(b, v) + } + } + + for v := range aAndBDedupe { + aAndB = append(aAndB, v) + } + sort.Strings(aAndB) + + return a, aAndB, b +} + +func isInSlice(slice []string, value string) bool { + i := sort.SearchStrings(slice, value) + return i < len(slice) && value == slice[i] +} diff --git a/tests/ci/x509/limbo-report/go.mod b/tests/ci/x509/limbo-report/go.mod new file mode 100644 index 0000000000..6e164513d0 --- /dev/null +++ b/tests/ci/x509/limbo-report/go.mod @@ -0,0 +1,5 @@ +module github.com/aws/aws-lc/tests/ci/x509/limbo-report + +go 1.17 + +require github.com/google/go-cmp v0.6.0 diff --git a/tests/ci/x509/limbo-report/go.sum b/tests/ci/x509/limbo-report/go.sum new file mode 100644 index 0000000000..5a8d551d88 --- /dev/null +++ b/tests/ci/x509/limbo-report/go.sum @@ -0,0 +1,2 @@ +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/tests/ci/x509/limbo-report/limbo.go b/tests/ci/x509/limbo-report/limbo.go new file mode 100644 index 0000000000..12d42af69e --- /dev/null +++ b/tests/ci/x509/limbo-report/limbo.go @@ -0,0 +1,271 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +package main + +import ( + "encoding/json" + "fmt" + "sort" + "strings" +) + +type Result string + +func (r *Result) FromString(value string) error { + if r == nil { + return fmt.Errorf("unexpected nil: %T", r) + } + + var result Result + + switch { + case strings.EqualFold(string(skippedResult), value): + result = skippedResult + case strings.EqualFold(string(successResult), value): + result = successResult + case strings.EqualFold(string(failureResult), value): + result = failureResult + default: + return fmt.Errorf("unknown result value: %v", value) + } + + *r = result + + return nil +} + +func (r *Result) UnmarshalJSON(bytes []byte) error { + if r == nil { + return fmt.Errorf("unexpected json unmarshal into nil: %T", r) + } + + var str string + + if err := json.Unmarshal(bytes, &str); err != nil { + return err + } + + if err := r.FromString(str); err != nil { + return err + } + + return nil +} + +const ( + skippedResult Result = "SKIPPED" + successResult Result = "SUCCESS" + failureResult Result = "FAILURE" +) + +type Judgement string + +func (j *Judgement) FromString(value string) error { + if j == nil { + return fmt.Errorf("unexpected nil: %T", j) + } + + var judgement Judgement + + switch { + case strings.EqualFold(string(skippedJudgement), value): + judgement = (skippedJudgement) + case strings.EqualFold(string(unexpectedFailureJudgement), value): + judgement = (unexpectedFailureJudgement) + case strings.EqualFold(string(unexpectedPassJudgement), value): + judgement = (unexpectedPassJudgement) + case strings.EqualFold(string(passJudgement), value): + judgement = (passJudgement) + default: + return fmt.Errorf("unknown judgement value: %v", value) + } + + *j = judgement + + return nil +} + +func (j *Judgement) UnmarshalJSON(bytes []byte) error { + if j == nil { + return fmt.Errorf("unexpected json unmarshal into nil: %T", j) + } + + var str string + + if err := json.Unmarshal(bytes, &str); err != nil { + return err + } + + if err := j.FromString(str); err != nil { + return err + } + + return nil +} + +const ( + skippedJudgement Judgement = "SKIPPED" + unexpectedFailureJudgement Judgement = "UNEXPECTED_FAILURE" + unexpectedPassJudgement Judgement = "UNEXPECTED_PASS" + passJudgement Judgement = "PASS" +) + +func Judgements() []Judgement { + return []Judgement{passJudgement, skippedJudgement, unexpectedFailureJudgement, unexpectedPassJudgement} +} + +type TestCaseMap map[string]TestCase + +func (m *TestCaseMap) UnmarshalJSON(data []byte) error { + var tc_slice []TestCase + + if err := json.Unmarshal(data, &tc_slice); err != nil { + return err + } + + if m == nil { + return fmt.Errorf("unexpected nil: %T", m) + } + + tc_map := make(TestCaseMap, len(tc_slice)) + + for _, tc := range tc_slice { + if _, ok := tc_map[tc.ID]; ok { + return fmt.Errorf("duplicate test case id: %v", tc.ID) + } + tc_map[tc.ID] = tc + } + + *m = tc_map + + return nil +} + +type Limbo struct { + Version uint `json:"version"` + TestCases TestCaseMap `json:"testcases"` +} + +type TestCase struct { + ID string `json:"id"` + Description string `json:"description"` + ExpectedResult Result `json:"expected_result"` +} + +type HarnessResults struct { + Harness string `json:"harness"` + Results TestCaseResultMap `json:"results"` +} + +// Annotate will use the provide Limbo test case descriptors to fill in the judgement fields on this harness result. +func (hr *HarnessResults) Annotate(limbo *Limbo) error { + if limbo == nil { + return fmt.Errorf("limbo data must not be nil") + } + + for id := range hr.Results { + tr := hr.Results[id] + + tc, ok := limbo.TestCases[id] + if !ok { + return fmt.Errorf("missing test case descriptor: %v", id) + } + + judgement, err := getJudgement(tc.ExpectedResult, tr.ActualResult) + if err != nil { + return fmt.Errorf("unexpected result: (%v, %v)", tc.ExpectedResult, tr.ActualResult) + } + + tr.Judgement = judgement + tr.Description = tc.Description + tr.ExpectedResult = tc.ExpectedResult + + hr.Results[id] = tr + } + + return nil +} + +type TestCaseResultMap map[string]AnnotatedTestCaseResult + +func (m TestCaseResultMap) MarshalJSON() ([]byte, error) { + if m == nil { + return nil, fmt.Errorf("unexpected marshall of nil to json: %T", m) + } + + var sortedIds []string + + for id, tc := range m { + // This shouldn't happen if our unmarshal was correct, but sanity check + if id != tc.ID { + return nil, fmt.Errorf("unexpected id consistency during json marshal: %s != %s", id, tc.ID) + } + sortedIds = append(sortedIds, id) + } + sort.Strings(sortedIds) + + var slice []*AnnotatedTestCaseResult + for _, id := range sortedIds { + tc := m[id] + slice = append(slice, &tc) + } + + return json.Marshal(&slice) +} + +func (m *TestCaseResultMap) UnmarshalJSON(data []byte) error { + if m == nil { + return fmt.Errorf("unexpected nil: %T", m) + } + + var tc_slice []AnnotatedTestCaseResult + + if err := json.Unmarshal(data, &tc_slice); err != nil { + return err + } + + tc_map := make(TestCaseResultMap, len(tc_slice)) + + for _, tc := range tc_slice { + if _, ok := tc_map[tc.ID]; ok { + return fmt.Errorf("duplicate test case id: %v", tc.ID) + } + tc_map[tc.ID] = tc + } + + *m = tc_map + + return nil +} + +type TestCaseResult struct { + ID string `json:"id"` + ActualResult Result `json:"actual_result"` + Context string `json:"context"` +} + +type AnnotatedTestCaseResult struct { + TestCaseResult + // These are additional fields we've annotated to the result. + // This eliminates the need to later calculate or cross-reference from the limbo.json file. + ExpectedResult Result `json:"expected_result,omitempty"` + Judgement Judgement `json:"judgement,omitempty"` + Description string `json:"description,omitempty"` +} + +func getJudgement(expected, result Result) (judgement Judgement, err error) { + if result == skippedResult { + judgement = skippedJudgement + } else if expected == result { + judgement = passJudgement + } else if expected == successResult && result == failureResult { + judgement = unexpectedFailureJudgement + } else if expected == failureResult && result == successResult { + judgement = unexpectedPassJudgement + } else { + return "", fmt.Errorf("unexpected result: (%v, %v)", expected, result) + } + + return judgement, nil +} diff --git a/tests/ci/x509/limbo-report/main.go b/tests/ci/x509/limbo-report/main.go new file mode 100644 index 0000000000..b91c70b0e5 --- /dev/null +++ b/tests/ci/x509/limbo-report/main.go @@ -0,0 +1,49 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +package main + +import ( + "flag" + "fmt" + "log" + "os" + "strings" +) + +func init() { + flag.Usage = printHelp +} + +func printHelp() { + var builder strings.Builder + builder.WriteString("Usage:\n\n") + builder.WriteString(annotateHelpDoc) + builder.WriteRune('\n') + builder.WriteString(diffHelp) + builder.WriteRune('\n') + fmt.Fprint(os.Stderr, builder.String()) + os.Exit(0) +} + +func main() { + flag.Parse() + + var err error + arg := flag.Arg(0) + switch { + case strings.EqualFold("annotate", arg): + err = runAnnotateCommand(flag.Args()[1:]) + case strings.EqualFold("diff", arg): + err = runDiffCommand(flag.Args()[1:]) + case strings.EqualFold("help", arg): + fallthrough + default: + printHelp() + return + } + + if err != nil { + log.Fatal(err) + } +} diff --git a/tests/ci/x509/limbo-report/main_test.go b/tests/ci/x509/limbo-report/main_test.go new file mode 100644 index 0000000000..dfd495e92b --- /dev/null +++ b/tests/ci/x509/limbo-report/main_test.go @@ -0,0 +1,931 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestAnnotateHarnessResult(t *testing.T) { + cases := []struct { + Results []byte + Limbo []byte + Expected HarnessResults + ExpectedErr string + }{ + { + Results: []byte(`{ + "harness": "stub", + "results": [ + { + "actual_result": "SUCCESS", + "id": "expected_pass" + }, + { + "actual_result": "FAILURE", + "context": "the reason", + "id": "expected_failure" + }, + { + "actual_result": "SKIPPED", + "id": "skipped_expected_success" + }, + { + "actual_result": "SKIPPED", + "id": "skipped_expected_failure" + }, + { + "actual_result": "SUCCESS", + "id": "unexpected_pass" + }, + { + "actual_result": "FAILURE", + "context": "the unexpected reason", + "id": "unexpected_failure" + } + ] +}`), + Limbo: []byte(`{ + "version": 1, + "testcases": [ + { + "expected_result": "SUCCESS", + "id": "expected_pass", + "description": "this has a description" + }, + { + "expected_result": "FAILURE", + "id": "expected_failure" + }, + { + "expected_result": "SUCCESS", + "id": "skipped_expected_success" + }, + { + "expected_result": "FAILURE", + "id": "skipped_expected_failure" + }, + { + "expected_result": "FAILURE", + "id": "unexpected_pass" + }, + { + "expected_result": "SUCCESS", + "id": "unexpected_failure" + } + ] +}`), + Expected: HarnessResults{ + Harness: "stub", + Results: map[string]AnnotatedTestCaseResult{ + "expected_pass": { + TestCaseResult: TestCaseResult{ + ActualResult: successResult, + ID: "expected_pass", + }, + ExpectedResult: successResult, + Judgement: passJudgement, + Description: "this has a description", + }, + "expected_failure": { + TestCaseResult: TestCaseResult{ + ActualResult: failureResult, + Context: "the reason", + ID: "expected_failure", + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + "skipped_expected_success": { + TestCaseResult: TestCaseResult{ + ActualResult: skippedResult, + ID: "skipped_expected_success", + }, + ExpectedResult: successResult, + Judgement: skippedJudgement, + }, + "skipped_expected_failure": { + TestCaseResult: TestCaseResult{ + ActualResult: skippedResult, + ID: "skipped_expected_failure", + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "unexpected_pass": { + TestCaseResult: TestCaseResult{ + ActualResult: successResult, + ID: "unexpected_pass", + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "unexpected_failure": { + TestCaseResult: TestCaseResult{ + ActualResult: failureResult, + Context: "the unexpected reason", + ID: "unexpected_failure", + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + }, + { + Limbo: []byte(`{ + "version": 1, + "testcases": [ + { + "id": "bad_expected_result", + "expected_result": "biz" + } + ] +}`), + Results: []byte(`{}`), + ExpectedErr: "unknown result value: biz", + }, + { + Limbo: []byte(`{ + "version": 1, + "testcases": [ + { + "id": "bad_expected_result", + "expected_result": "SUCCESS" + } + ] +}`), + Results: []byte(`{ + "harness": "stub", + "results": [ + { + "id": "bad_actual_result", + "actual_result": "biz" + } + ] +}`), + ExpectedErr: "unknown result value: biz", + }, + { + Limbo: []byte(`{ + "version": 1, + "testcases": [ + { + "id": "mot_missing_id", + "expected_result": "FAILURE" + } + ] +}`), + Results: []byte(`{ + "harness": "stub", + "results": [ + { + "id": "missing_id", + "actual_result": "SUCCESS" + } + ] +}`), + ExpectedErr: "missing test case descriptor: missing_id", + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprint(i), func(t *testing.T) { + var limbo Limbo + if err := json.Unmarshal(tc.Limbo, &limbo); err != nil { + if len(tc.ExpectedErr) == 0 { + t.Fatalf("unexpected err: %v", err) + } else if !strings.Contains(err.Error(), tc.ExpectedErr) { + t.Fatalf("err didn't contain expected string, wanted %v, got %v", tc.ExpectedErr, err) + } else { + return + } + } + + var harness HarnessResults + if err := json.Unmarshal(tc.Results, &harness); err != nil { + if len(tc.ExpectedErr) == 0 { + t.Fatalf("unexpected err: %v", err) + } else if !strings.Contains(err.Error(), tc.ExpectedErr) { + t.Fatalf("err didn't contain expected string, wanted %v, got %v", tc.ExpectedErr, err) + } else { + return + } + } + + if err := harness.Annotate(&limbo); err != nil { + if len(tc.ExpectedErr) == 0 { + t.Fatalf("unexpected err: %v", err) + } else if !strings.Contains(err.Error(), tc.ExpectedErr) { + t.Fatalf("err didn't contain expected string, wanted %v, got %v", tc.ExpectedErr, err) + } else { + return + } + } + + if diff := cmp.Diff(&harness, &tc.Expected); len(diff) > 0 { + t.Fatal(diff) + } + }) + } +} + +func TestDiff(t *testing.T) { + cases := []struct { + ResultsBefore HarnessResults + ResultsAfter HarnessResults + Expected Diff + ExpectedTotal int + ExpectedTotalRemoved int + ExpectedTotalAdded int + ExpectedTotalChanged int + ExpectedTotalUnchanged int + }{ + { + ResultsBefore: HarnessResults{ + Results: TestCaseResultMap{ + "left_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "left_pass", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "left_skipped": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "left_skipped", + ActualResult: skippedResult, + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "left_expect_fail": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "left_expect_fail", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "left_expect_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "left_expect_pass", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + ResultsAfter: HarnessResults{}, + Expected: Diff{ + Removed: map[Judgement][]string{ + passJudgement: {"left_pass"}, + skippedJudgement: {"left_skipped"}, + unexpectedFailureJudgement: {"left_expect_pass"}, + unexpectedPassJudgement: {"left_expect_fail"}, + }, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{}, + }, + ExpectedTotalRemoved: 4, + }, + { + ResultsBefore: HarnessResults{}, + ResultsAfter: HarnessResults{ + Results: TestCaseResultMap{ + "right_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "right_pass", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "right_skipped": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "right_skipped", + ActualResult: skippedResult, + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "right_expect_fail": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "right_expect_fail", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "right_expect_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "right_expect_pass", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + Expected: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{ + passJudgement: {"right_pass"}, + skippedJudgement: {"right_skipped"}, + unexpectedFailureJudgement: {"right_expect_pass"}, + unexpectedPassJudgement: {"right_expect_fail"}, + }, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{}, + }, + ExpectedTotal: 4, + ExpectedTotalAdded: 4, + }, + { + ResultsBefore: HarnessResults{ + Results: TestCaseResultMap{ + "both_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_pass", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "both_skipped": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_skipped", + ActualResult: skippedResult, + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "both_expect_fail": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_expect_fail", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "both_expect_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_expect_pass", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + ResultsAfter: HarnessResults{ + Results: TestCaseResultMap{ + "both_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_pass", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "both_skipped": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_skipped", + ActualResult: skippedResult, + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "both_expect_fail": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_expect_fail", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "both_expect_pass": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "both_expect_pass", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + Expected: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{ + passJudgement: {"both_pass"}, + skippedJudgement: {"both_skipped"}, + unexpectedFailureJudgement: {"both_expect_pass"}, + unexpectedPassJudgement: {"both_expect_fail"}, + }, + }, + ExpectedTotal: 4, + ExpectedTotalUnchanged: 4, + }, + { + ResultsBefore: HarnessResults{ + Results: TestCaseResultMap{ + "changed1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "changed2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed2", + ActualResult: skippedResult, + }, + ExpectedResult: failureResult, + Judgement: skippedJudgement, + }, + "changed3": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed3", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "changed4": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed4", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + }, + }, + ResultsAfter: HarnessResults{ + Results: TestCaseResultMap{ + "changed1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed1", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + "changed2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed2", + ActualResult: successResult, + }, + ExpectedResult: failureResult, + Judgement: unexpectedPassJudgement, + }, + "changed3": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed3", + ActualResult: failureResult, + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + "changed4": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed4", + ActualResult: skippedResult, + }, + ExpectedResult: successResult, + Judgement: skippedJudgement, + }, + }, + }, + Expected: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{ + passJudgement: {{ID: "changed3", Was: "UNEXPECTED_PASS"}}, + skippedJudgement: {{ID: "changed4", Was: "UNEXPECTED_FAILURE"}}, + unexpectedFailureJudgement: {{ID: "changed1", Was: "PASS"}}, + unexpectedPassJudgement: {{ID: "changed2", Was: "SKIPPED"}}, + }, + Unchanged: map[Judgement][]string{}, + }, + ExpectedTotal: 4, + ExpectedTotalChanged: 4, + }, + { + ResultsBefore: HarnessResults{ + Results: TestCaseResultMap{ + "before1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "before1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "before2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "before2", + ActualResult: failureResult, + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + "same1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "same1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "same2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "same2", + ActualResult: failureResult, + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + "changed1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "changed2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed2", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + }, + }, + ResultsAfter: HarnessResults{ + Results: TestCaseResultMap{ + "same1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "same1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "same2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "same2", + ActualResult: failureResult, + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + "changed1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed1", + ActualResult: failureResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + "changed2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "changed2", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: unexpectedFailureJudgement, + }, + "new1": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "new1", + ActualResult: successResult, + }, + ExpectedResult: successResult, + Judgement: passJudgement, + }, + "new2": AnnotatedTestCaseResult{ + TestCaseResult: TestCaseResult{ + ID: "new2", + ActualResult: failureResult, + }, + ExpectedResult: failureResult, + Judgement: passJudgement, + }, + }, + }, + Expected: Diff{ + Removed: map[Judgement][]string{ + passJudgement: {"before1", "before2"}, + }, + Added: map[Judgement][]string{ + passJudgement: {"new1", "new2"}, + }, + Changed: map[Judgement][]ChangedResult{ + unexpectedFailureJudgement: {{ID: "changed1", Was: "PASS"}, {ID: "changed2", Was: "PASS"}}, + }, + Unchanged: map[Judgement][]string{ + passJudgement: {"same1", "same2"}, + }, + }, + ExpectedTotal: 6, + ExpectedTotalRemoved: 2, + ExpectedTotalAdded: 2, + ExpectedTotalChanged: 2, + ExpectedTotalUnchanged: 2, + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + diff, err := diffReports(&tc.ResultsBefore, &tc.ResultsAfter) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(tc.Expected, diff); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(diff.Total(), tc.ExpectedTotal); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(diff.TotalRemoved(), tc.ExpectedTotalRemoved); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(diff.TotalAdded(), tc.ExpectedTotalAdded); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(diff.TotalChanged(), tc.ExpectedTotalChanged); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(diff.TotalUnchanged(), tc.ExpectedTotalUnchanged); len(diff) > 0 { + t.Error(diff) + } + }) + } +} + +func TestIntersection(t *testing.T) { + cases := []struct { + Left []string + Right []string + ExpectLeft []string + ExpectBoth []string + ExpectRight []string + }{ + { + Left: []string{"left"}, + ExpectLeft: []string{"left"}, + }, + { + Right: []string{"right"}, + ExpectRight: []string{"right"}, + }, + { + Left: []string{"left"}, + Right: []string{"right"}, + ExpectLeft: []string{"left"}, + ExpectRight: []string{"right"}, + }, + { + Left: []string{"both"}, + Right: []string{"both"}, + ExpectBoth: []string{"both"}, + }, + { + Left: []string{"both", "left"}, + Right: []string{"both", "right"}, + ExpectLeft: []string{"left"}, + ExpectBoth: []string{"both"}, + ExpectRight: []string{"right"}, + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + left, inter, right := intersection(tc.Left, tc.Right) + if diff := cmp.Diff(tc.ExpectLeft, left); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(tc.ExpectBoth, inter); len(diff) > 0 { + t.Error(diff) + } + if diff := cmp.Diff(tc.ExpectRight, right); len(diff) > 0 { + t.Error(diff) + } + }) + } +} + +func TestDiffNeedsAttention(t *testing.T) { + cases := []struct { + Diff Diff + Expect bool + }{ + { + Diff: Diff{ + Removed: map[Judgement][]string{ + skippedJudgement: {"skipped"}, + }, + Added: map[Judgement][]string{ + passJudgement: {"added_pass"}, + skippedJudgement: {"added_skipped"}, + }, + Changed: map[Judgement][]ChangedResult{ + skippedJudgement: { + { + ID: "changed_skipped", + Was: passJudgement, + }, + }, + passJudgement: { + { + ID: "changed_passed", + Was: unexpectedFailureJudgement, + }, + }, + }, + Unchanged: map[Judgement][]string{ + skippedJudgement: {"unchanged_skipped"}, + passJudgement: {"unchanged_pass"}, + unexpectedFailureJudgement: {"unchanged_failure1"}, + unexpectedPassJudgement: {"unchanged_failure2"}, + }, + }, + Expect: false, + }, + { + Diff: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{ + unexpectedFailureJudgement: {"failure"}, + }, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{}, + }, + Expect: true, + }, + { + Diff: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{ + unexpectedPassJudgement: {"failure"}, + }, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{}, + }, + Expect: true, + }, + { + Diff: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{ + unexpectedFailureJudgement: {{ + ID: "failure", + Was: passJudgement, + }}, + }, + Unchanged: map[Judgement][]string{}, + }, + Expect: true, + }, + { + Diff: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{ + unexpectedPassJudgement: {{ + ID: "failure", + Was: passJudgement, + }}, + }, + Unchanged: map[Judgement][]string{}, + }, + Expect: true, + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprint(i), func(t *testing.T) { + if got := tc.Diff.NeedsAttention(); tc.Expect != got { + t.Fatalf("expected %v, got %v", tc.Expect, got) + } + }) + } +} + +func TestRenderDiff(t *testing.T) { + cases := []struct { + Diff Diff + Expect string + }{ + { + Diff: Diff{ + Removed: map[Judgement][]string{ + skippedJudgement: {"skipped"}, + }, + Added: map[Judgement][]string{ + passJudgement: {"added_pass"}, + skippedJudgement: {"added_skipped"}, + }, + Changed: map[Judgement][]ChangedResult{ + skippedJudgement: { + { + ID: "changed_skipped", + Was: passJudgement, + }, + }, + passJudgement: { + { + ID: "changed_passed", + Was: unexpectedFailureJudgement, + }, + }, + }, + Unchanged: map[Judgement][]string{ + skippedJudgement: {"unchanged_skipped"}, + passJudgement: {"unchanged_pass"}, + unexpectedFailureJudgement: {"unchanged_failure1"}, + unexpectedPassJudgement: {"unchanged_failure2"}, + }, + }, + Expect: `PASS: 3, SKIPPED: 3, UNEXPECTED_FAILURE: 1, UNEXPECTED_PASS: 1 + +Report Breakdown: + 2 added + 1 removed + 2 changed + 4 unchanged + +Added PASS: + added_pass + +Added SKIPPED: + added_skipped + + +Removed SKIPPED: + skipped + + +Changed to PASS: + changed_passed (previously UNEXPECTED_FAILURE) + +Changed to SKIPPED: + changed_skipped (previously PASS) + + +`, + }, + { + Diff: Diff{ + Removed: map[Judgement][]string{}, + Added: map[Judgement][]string{}, + Changed: map[Judgement][]ChangedResult{}, + Unchanged: map[Judgement][]string{ + skippedJudgement: {"unchanged_skipped"}, + passJudgement: {"unchanged_pass"}, + unexpectedFailureJudgement: {"unchanged_failure1"}, + unexpectedPassJudgement: {"unchanged_failure2"}, + }, + }, + Expect: `PASS: 1, SKIPPED: 1, UNEXPECTED_FAILURE: 1, UNEXPECTED_PASS: 1 + +Report Breakdown: + 0 added + 0 removed + 0 changed + 4 unchanged + +`, + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprint(i), func(t *testing.T) { + buffer := bytes.NewBuffer(nil) + if err := tc.Diff.Render(buffer); err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(tc.Expect, buffer.String()); len(diff) > 0 { + t.Fatal(diff) + } + }) + } +} diff --git a/tests/ci/x509/x509-limbo.patch b/tests/ci/x509/x509-limbo.patch new file mode 100644 index 0000000000..9ac10db6de --- /dev/null +++ b/tests/ci/x509/x509-limbo.patch @@ -0,0 +1,33252 @@ +From c9801cd216fa64be8045d948cc9f73a3fad025a2 Mon Sep 17 00:00:00 2001 +From: Sean McGrail +Date: Mon, 30 Sep 2024 19:29:48 +0000 +Subject: [PATCH] Support for AWS Libcrypto (AWS-LC) + +--- + Makefile | 7 +- + harness/aws-lc/.gitignore | 2 + + harness/aws-lc/Makefile | 26 + + harness/aws-lc/README.md | 26 + + harness/aws-lc/aws-lc.dockerfile | 27 + + harness/aws-lc/date.hpp | 8234 ++++++++++ + harness/aws-lc/json.hpp | 24596 +++++++++++++++++++++++++++++ + harness/aws-lc/main.cpp | 253 + + 8 files changed, 33170 insertions(+), 1 deletion(-) + create mode 100644 harness/aws-lc/.gitignore + create mode 100644 harness/aws-lc/Makefile + create mode 100644 harness/aws-lc/README.md + create mode 100644 harness/aws-lc/aws-lc.dockerfile + create mode 100644 harness/aws-lc/date.hpp + create mode 100644 harness/aws-lc/json.hpp + create mode 100644 harness/aws-lc/main.cpp + +diff --git a/Makefile b/Makefile +index b81cf83..416c5c8 100644 +--- a/Makefile ++++ b/Makefile +@@ -110,8 +110,13 @@ test-certvalidator: $(NEEDS_VENV) + test-gnutls: + $(MAKE) run ARGS="harness --output ./results/gnutls.json -- ./$(VENV_BIN)/python ./harness/gnutls/test-gnutls" + ++.PHONY: test-aws-lc ++test-aws-lc: ++ $(MAKE) -C harness/aws-lc build-image ++ $(MAKE) run ARGS="harness --output ./results/aws-lc.json -- docker run --platform linux/amd64 --rm -i x509-limbo-aws-lc" ++ + .PHONY: test +-test: test-go test-openssl test-rust-webpki test-rustls-webpki test-pyca-cryptography test-certvalidator test-gnutls ++test: test-go test-openssl test-rust-webpki test-rustls-webpki test-pyca-cryptography test-certvalidator test-gnutls test-aws-lc + + .PHONY: site + site: $(NEEDS_VENV) +diff --git a/harness/aws-lc/.gitignore b/harness/aws-lc/.gitignore +new file mode 100644 +index 0000000..9bc5102 +--- /dev/null ++++ b/harness/aws-lc/.gitignore +@@ -0,0 +1,2 @@ ++main ++results.json +diff --git a/harness/aws-lc/Makefile b/harness/aws-lc/Makefile +new file mode 100644 +index 0000000..2305b42 +--- /dev/null ++++ b/harness/aws-lc/Makefile +@@ -0,0 +1,26 @@ ++AWS_LC_SRC_DIR ?= ++LIBRPATH = $(shell env PKG_CONFIG_PATH=${PKG_CONFIG_PATH} pkg-config --variable=libdir libcrypto) ++CXXFLAGS = -std=c++17 -Wl,-rpath=${LIBRPATH} ++CPPFLAGS = $(shell env PKG_CONFIG_PATH=${PKG_CONFIG_PATH} pkg-config --cflags libcrypto) ++LDLIBS = $(shell env PKG_CONFIG_PATH=${PKG_CONFIG_PATH} pkg-config --libs libcrypto) ++ ++.PHONY: all ++all: main ++ ++.PHONY: debug ++debug: CXXFLAGS += -g -fsanitize=address,undefined ++debug: main ++ ++.PHONY: clean ++clean: ++ rm -f main ++ ++.PHONY: verify-aws-lc-source ++verify-aws-lc-source: ++ @if [ test -z "${AWS_LC_SRC_DIR}" ]; then \ ++ echo "AWS_LC_SRC_DIR environment variable is missing and is required to specify AWS-LC source location" && false; \ ++ fi ++ ++.PHONY: build-image ++build-image: verify-aws-lc-source aws-lc.dockerfile ++ docker build --platform linux/amd64 -f aws-lc.dockerfile --build-context aws_lc_src=${AWS_LC_SRC_DIR} . -t x509-limbo-aws-lc +diff --git a/harness/aws-lc/README.md b/harness/aws-lc/README.md +new file mode 100644 +index 0000000..a6bc5af +--- /dev/null ++++ b/harness/aws-lc/README.md +@@ -0,0 +1,26 @@ ++# OpenSSL test harness for x509-limbo ++ ++This directory contains a basic test harness for running the x509-testsuite ++against AWS Libcrypto (AWS-LC). ++ ++## Building ++ ++On Linux with OpenSSL installed, building should be as simple as: ++ ++```bash ++# build normally ++make ++ ++# build with sanitizers, etc. ++make debug ++``` ++ ++On macOS, you'll need to tell the build where to find the version of OpenSSL ++to use. The easiest way to do that is to use `brew` and `PKG_CONFIG_PATH`, e.g.: ++ ++```bash ++# install the version of OpenSSL you'd like to test ++brew install openssl@3.1 ++ ++PKG_CONFIG_PATH="$(brew --prefix)/opt/openssl@3.1/lib/pkgconfig" make ++``` +diff --git a/harness/aws-lc/aws-lc.dockerfile b/harness/aws-lc/aws-lc.dockerfile +new file mode 100644 +index 0000000..79db8cb +--- /dev/null ++++ b/harness/aws-lc/aws-lc.dockerfile +@@ -0,0 +1,27 @@ ++FROM amazonlinux:2023 AS aws_lc_build ++ ++RUN yum install -y ninja-build cmake golang gcc gcc-c++ git ++ ++COPY --from=aws_lc_src . /src ++ ++WORKDIR /src ++ ++RUN cmake -B build -S . -GNinja -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/opt/aws-lc && \ ++ cmake --build build && \ ++ cmake --install build ++ ++FROM amazonlinux:2023 ++ ++RUN yum install -y gcc gcc-c++ make ++ ++COPY --from=aws_lc_build /opt/aws-lc /opt/aws-lc ++ ++WORKDIR / ++ ++ENV PKG_CONFIG_PATH=/opt/aws-lc/lib64/pkgconfig ++ ++COPY date.hpp json.hpp main.cpp Makefile / ++ ++RUN make ++ ++ENTRYPOINT ["./main"] +diff --git a/harness/aws-lc/date.hpp b/harness/aws-lc/date.hpp +new file mode 100644 +index 0000000..e9c3782 +--- /dev/null ++++ b/harness/aws-lc/date.hpp +@@ -0,0 +1,8234 @@ ++#ifndef DATE_H ++#define DATE_H ++ ++// The MIT License (MIT) ++// ++// Copyright (c) 2015, 2016, 2017 Howard Hinnant ++// Copyright (c) 2016 Adrian Colomitchi ++// Copyright (c) 2017 Florian Dang ++// Copyright (c) 2017 Paul Thompson ++// Copyright (c) 2018, 2019 Tomasz Kamiński ++// Copyright (c) 2019 Jiangang Zhuang ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy ++// of this software and associated documentation files (the "Software"), to deal ++// in the Software without restriction, including without limitation the rights ++// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++// copies of the Software, and to permit persons to whom the Software is ++// furnished to do so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++// ++// Our apologies. When the previous paragraph was written, lowercase had not yet ++// been invented (that would involve another several millennia of evolution). ++// We did not mean to shout. ++ ++#ifndef HAS_STRING_VIEW ++# if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) ++# define HAS_STRING_VIEW 1 ++# else ++# define HAS_STRING_VIEW 0 ++# endif ++#endif // HAS_STRING_VIEW ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if HAS_STRING_VIEW ++# include ++#endif ++#include ++#include ++ ++#ifdef __GNUC__ ++# pragma GCC diagnostic push ++# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) ++# pragma GCC diagnostic ignored "-Wpedantic" ++# endif ++# if __GNUC__ < 5 ++ // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers ++# pragma GCC diagnostic ignored "-Wmissing-field-initializers" ++# endif ++#endif ++ ++#ifdef _MSC_VER ++# pragma warning(push) ++// warning C4127: conditional expression is constant ++# pragma warning(disable : 4127) ++#endif ++ ++namespace date ++{ ++ ++//---------------+ ++// Configuration | ++//---------------+ ++ ++#ifndef ONLY_C_LOCALE ++# define ONLY_C_LOCALE 0 ++#endif ++ ++#if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910)) ++// MSVC ++# ifndef _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING ++# define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING ++# endif ++# if _MSC_VER < 1910 ++// before VS2017 ++# define CONSTDATA const ++# define CONSTCD11 ++# define CONSTCD14 ++# define NOEXCEPT _NOEXCEPT ++# else ++// VS2017 and later ++# define CONSTDATA constexpr const ++# define CONSTCD11 constexpr ++# define CONSTCD14 constexpr ++# define NOEXCEPT noexcept ++# endif ++ ++#elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150 ++// Oracle Developer Studio 12.6 and earlier ++# define CONSTDATA constexpr const ++# define CONSTCD11 constexpr ++# define CONSTCD14 ++# define NOEXCEPT noexcept ++ ++#elif __cplusplus >= 201402 ++// C++14 ++# define CONSTDATA constexpr const ++# define CONSTCD11 constexpr ++# define CONSTCD14 constexpr ++# define NOEXCEPT noexcept ++#else ++// C++11 ++# define CONSTDATA constexpr const ++# define CONSTCD11 constexpr ++# define CONSTCD14 ++# define NOEXCEPT noexcept ++#endif ++ ++#ifndef HAS_UNCAUGHT_EXCEPTIONS ++# if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) ++# define HAS_UNCAUGHT_EXCEPTIONS 1 ++# else ++# define HAS_UNCAUGHT_EXCEPTIONS 0 ++# endif ++#endif // HAS_UNCAUGHT_EXCEPTIONS ++ ++#ifndef HAS_VOID_T ++# if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) ++# define HAS_VOID_T 1 ++# else ++# define HAS_VOID_T 0 ++# endif ++#endif // HAS_VOID_T ++ ++// Protect from Oracle sun macro ++#ifdef sun ++# undef sun ++#endif ++ ++// Work around for a NVCC compiler bug which causes it to fail ++// to compile std::ratio_{multiply,divide} when used directly ++// in the std::chrono::duration template instantiations below ++namespace detail { ++template ++using ratio_multiply = decltype(std::ratio_multiply{}); ++ ++template ++using ratio_divide = decltype(std::ratio_divide{}); ++} // namespace detail ++ ++//-----------+ ++// Interface | ++//-----------+ ++ ++// durations ++ ++using days = std::chrono::duration ++ , std::chrono::hours::period>>; ++ ++using weeks = std::chrono::duration ++ , days::period>>; ++ ++using years = std::chrono::duration ++ , days::period>>; ++ ++using months = std::chrono::duration ++ >>; ++ ++// time_point ++ ++template ++ using sys_time = std::chrono::time_point; ++ ++using sys_days = sys_time; ++using sys_seconds = sys_time; ++ ++struct local_t {}; ++ ++template ++ using local_time = std::chrono::time_point; ++ ++using local_seconds = local_time; ++using local_days = local_time; ++ ++// types ++ ++struct last_spec ++{ ++ explicit last_spec() = default; ++}; ++ ++class day; ++class month; ++class year; ++ ++class weekday; ++class weekday_indexed; ++class weekday_last; ++ ++class month_day; ++class month_day_last; ++class month_weekday; ++class month_weekday_last; ++ ++class year_month; ++ ++class year_month_day; ++class year_month_day_last; ++class year_month_weekday; ++class year_month_weekday_last; ++ ++// date composition operators ++ ++CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT; ++CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT; ++ ++CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT; ++CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT; ++CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT; ++CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT; ++CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT; ++ ++CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT; ++CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT; ++CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT; ++CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT; ++ ++CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT; ++CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT; ++CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT; ++CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT; ++ ++CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT; ++CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT; ++CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT; ++CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT; ++ ++CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT; ++CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT; ++CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT; ++CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT; ++CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT; ++CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT; ++ ++CONSTCD11 ++ year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT; ++CONSTCD11 ++ year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT; ++CONSTCD11 ++ year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT; ++CONSTCD11 ++ year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT; ++CONSTCD11 ++ year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator/(const year& y, const month_weekday& mwd) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator/(int y, const month_weekday& mwd) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator/(const month_weekday& mwd, const year& y) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator/(const month_weekday& mwd, int y) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator/(int y, const month_weekday_last& mwdl) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator/(const month_weekday_last& mwdl, int y) NOEXCEPT; ++ ++// Detailed interface ++ ++// day ++ ++class day ++{ ++ unsigned char d_; ++ ++public: ++ day() = default; ++ explicit CONSTCD11 day(unsigned d) NOEXCEPT; ++ ++ CONSTCD14 day& operator++() NOEXCEPT; ++ CONSTCD14 day operator++(int) NOEXCEPT; ++ CONSTCD14 day& operator--() NOEXCEPT; ++ CONSTCD14 day operator--(int) NOEXCEPT; ++ ++ CONSTCD14 day& operator+=(const days& d) NOEXCEPT; ++ CONSTCD14 day& operator-=(const days& d) NOEXCEPT; ++ ++ CONSTCD11 explicit operator unsigned() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT; ++CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT; ++CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT; ++ ++CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT; ++CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT; ++CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT; ++CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const day& d); ++ ++// month ++ ++class month ++{ ++ unsigned char m_; ++ ++public: ++ month() = default; ++ explicit CONSTCD11 month(unsigned m) NOEXCEPT; ++ ++ CONSTCD14 month& operator++() NOEXCEPT; ++ CONSTCD14 month operator++(int) NOEXCEPT; ++ CONSTCD14 month& operator--() NOEXCEPT; ++ CONSTCD14 month operator--(int) NOEXCEPT; ++ ++ CONSTCD14 month& operator+=(const months& m) NOEXCEPT; ++ CONSTCD14 month& operator-=(const months& m) NOEXCEPT; ++ ++ CONSTCD11 explicit operator unsigned() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT; ++CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT; ++CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT; ++ ++CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT; ++CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT; ++CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT; ++CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month& m); ++ ++// year ++ ++class year ++{ ++ short y_; ++ ++public: ++ year() = default; ++ explicit CONSTCD11 year(int y) NOEXCEPT; ++ ++ CONSTCD14 year& operator++() NOEXCEPT; ++ CONSTCD14 year operator++(int) NOEXCEPT; ++ CONSTCD14 year& operator--() NOEXCEPT; ++ CONSTCD14 year operator--(int) NOEXCEPT; ++ ++ CONSTCD14 year& operator+=(const years& y) NOEXCEPT; ++ CONSTCD14 year& operator-=(const years& y) NOEXCEPT; ++ ++ CONSTCD11 year operator-() const NOEXCEPT; ++ CONSTCD11 year operator+() const NOEXCEPT; ++ ++ CONSTCD11 bool is_leap() const NOEXCEPT; ++ ++ CONSTCD11 explicit operator int() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++ ++ static CONSTCD11 year min() NOEXCEPT { return year{-32767}; } ++ static CONSTCD11 year max() NOEXCEPT { return year{32767}; } ++}; ++ ++CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; ++CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; ++CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; ++ ++CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; ++CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; ++CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; ++CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year& y); ++ ++// weekday ++ ++class weekday ++{ ++ unsigned char wd_; ++public: ++ weekday() = default; ++ explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; ++ CONSTCD14 weekday(const sys_days& dp) NOEXCEPT; ++ CONSTCD14 explicit weekday(const local_days& dp) NOEXCEPT; ++ ++ CONSTCD14 weekday& operator++() NOEXCEPT; ++ CONSTCD14 weekday operator++(int) NOEXCEPT; ++ CONSTCD14 weekday& operator--() NOEXCEPT; ++ CONSTCD14 weekday operator--(int) NOEXCEPT; ++ ++ CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; ++ CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; ++ ++ CONSTCD11 bool ok() const NOEXCEPT; ++ ++ CONSTCD11 unsigned c_encoding() const NOEXCEPT; ++ CONSTCD11 unsigned iso_encoding() const NOEXCEPT; ++ ++ CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; ++ CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; ++ ++private: ++ static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT; ++ ++ friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; ++ friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; ++ friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; ++ template ++ friend std::basic_ostream& ++ operator<<(std::basic_ostream& os, const weekday& wd); ++ friend class weekday_indexed; ++}; ++ ++CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; ++ ++CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; ++CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; ++CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; ++CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday& wd); ++ ++// weekday_indexed ++ ++class weekday_indexed ++{ ++ unsigned char wd_ : 4; ++ unsigned char index_ : 4; ++ ++public: ++ weekday_indexed() = default; ++ CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT; ++ ++ CONSTCD11 date::weekday weekday() const NOEXCEPT; ++ CONSTCD11 unsigned index() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday_indexed& wdi); ++ ++// weekday_last ++ ++class weekday_last ++{ ++ date::weekday wd_; ++ ++public: ++ explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT; ++ ++ CONSTCD11 date::weekday weekday() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday_last& wdl); ++ ++namespace detail ++{ ++ ++struct unspecified_month_disambiguator {}; ++ ++} // namespace detail ++ ++// year_month ++ ++class year_month ++{ ++ date::year y_; ++ date::month m_; ++ ++public: ++ year_month() = default; ++ CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT; ++ ++ CONSTCD11 date::year year() const NOEXCEPT; ++ CONSTCD11 date::month month() const NOEXCEPT; ++ ++ template ++ CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT; ++ template ++ CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT; ++ CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT; ++ CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT; ++ ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT; ++ ++template ++CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT; ++template ++CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT; ++template ++CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT; ++ ++CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT; ++CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT; ++CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT; ++CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month& ym); ++ ++// month_day ++ ++class month_day ++{ ++ date::month m_; ++ date::day d_; ++ ++public: ++ month_day() = default; ++ CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT; ++ ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::day day() const NOEXCEPT; ++ ++ CONSTCD14 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT; ++CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT; ++CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_day& md); ++ ++// month_day_last ++ ++class month_day_last ++{ ++ date::month m_; ++ ++public: ++ CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT; ++ ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ++CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT; ++CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_day_last& mdl); ++ ++// month_weekday ++ ++class month_weekday ++{ ++ date::month m_; ++ date::weekday_indexed wdi_; ++public: ++ CONSTCD11 month_weekday(const date::month& m, ++ const date::weekday_indexed& wdi) NOEXCEPT; ++ ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; ++ ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_weekday& mwd); ++ ++// month_weekday_last ++ ++class month_weekday_last ++{ ++ date::month m_; ++ date::weekday_last wdl_; ++ ++public: ++ CONSTCD11 month_weekday_last(const date::month& m, ++ const date::weekday_last& wd) NOEXCEPT; ++ ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; ++ ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 ++ bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_weekday_last& mwdl); ++ ++// class year_month_day ++ ++class year_month_day ++{ ++ date::year y_; ++ date::month m_; ++ date::day d_; ++ ++public: ++ year_month_day() = default; ++ CONSTCD11 year_month_day(const date::year& y, const date::month& m, ++ const date::day& d) NOEXCEPT; ++ CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT; ++ ++ CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; ++ CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; ++ ++ template ++ CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT; ++ template ++ CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT; ++ CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT; ++ CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT; ++ ++ CONSTCD11 date::year year() const NOEXCEPT; ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::day day() const NOEXCEPT; ++ ++ CONSTCD14 operator sys_days() const NOEXCEPT; ++ CONSTCD14 explicit operator local_days() const NOEXCEPT; ++ CONSTCD14 bool ok() const NOEXCEPT; ++ ++private: ++ static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; ++ CONSTCD14 days to_days() const NOEXCEPT; ++}; ++ ++CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT; ++CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ++CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT; ++CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT; ++CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ++CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ++ ++template ++CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT; ++template ++CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT; ++template ++CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT; ++CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT; ++CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT; ++CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_day& ymd); ++ ++// year_month_day_last ++ ++class year_month_day_last ++{ ++ date::year y_; ++ date::month_day_last mdl_; ++ ++public: ++ CONSTCD11 year_month_day_last(const date::year& y, ++ const date::month_day_last& mdl) NOEXCEPT; ++ ++ template ++ CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT; ++ template ++ CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT; ++ CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT; ++ CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT; ++ ++ CONSTCD11 date::year year() const NOEXCEPT; ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT; ++ CONSTCD14 date::day day() const NOEXCEPT; ++ ++ CONSTCD14 operator sys_days() const NOEXCEPT; ++ CONSTCD14 explicit operator local_days() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++}; ++ ++CONSTCD11 ++ bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++CONSTCD11 ++ bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_day_last ++operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_day_last ++operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT; ++ ++CONSTCD11 ++year_month_day_last ++operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; ++ ++CONSTCD11 ++year_month_day_last ++operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_day_last ++operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; ++ ++CONSTCD11 ++year_month_day_last ++operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_day_last& ymdl); ++ ++// year_month_weekday ++ ++class year_month_weekday ++{ ++ date::year y_; ++ date::month m_; ++ date::weekday_indexed wdi_; ++ ++public: ++ year_month_weekday() = default; ++ CONSTCD11 year_month_weekday(const date::year& y, const date::month& m, ++ const date::weekday_indexed& wdi) NOEXCEPT; ++ CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT; ++ CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT; ++ ++ template ++ CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT; ++ template ++ CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT; ++ CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT; ++ CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT; ++ ++ CONSTCD11 date::year year() const NOEXCEPT; ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::weekday weekday() const NOEXCEPT; ++ CONSTCD11 unsigned index() const NOEXCEPT; ++ CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; ++ ++ CONSTCD14 operator sys_days() const NOEXCEPT; ++ CONSTCD14 explicit operator local_days() const NOEXCEPT; ++ CONSTCD14 bool ok() const NOEXCEPT; ++ ++private: ++ static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; ++ CONSTCD14 days to_days() const NOEXCEPT; ++}; ++ ++CONSTCD11 ++ bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; ++CONSTCD11 ++ bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday ++operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday ++operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday ++operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday ++operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi); ++ ++// year_month_weekday_last ++ ++class year_month_weekday_last ++{ ++ date::year y_; ++ date::month m_; ++ date::weekday_last wdl_; ++ ++public: ++ CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m, ++ const date::weekday_last& wdl) NOEXCEPT; ++ ++ template ++ CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT; ++ template ++ CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT; ++ CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT; ++ CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT; ++ ++ CONSTCD11 date::year year() const NOEXCEPT; ++ CONSTCD11 date::month month() const NOEXCEPT; ++ CONSTCD11 date::weekday weekday() const NOEXCEPT; ++ CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; ++ ++ CONSTCD14 operator sys_days() const NOEXCEPT; ++ CONSTCD14 explicit operator local_days() const NOEXCEPT; ++ CONSTCD11 bool ok() const NOEXCEPT; ++ ++private: ++ CONSTCD14 days to_days() const NOEXCEPT; ++}; ++ ++CONSTCD11 ++bool ++operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; ++ ++CONSTCD11 ++bool ++operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday_last ++operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday_last ++operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT; ++ ++template ++CONSTCD14 ++year_month_weekday_last ++operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; ++ ++CONSTCD11 ++year_month_weekday_last ++operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; ++ ++template ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl); ++ ++#if !defined(_MSC_VER) || (_MSC_VER >= 1900) ++inline namespace literals ++{ ++ ++CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT; ++CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT; ++ ++} // inline namespace literals ++#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) ++ ++// CONSTDATA date::month January{1}; ++// CONSTDATA date::month February{2}; ++// CONSTDATA date::month March{3}; ++// CONSTDATA date::month April{4}; ++// CONSTDATA date::month May{5}; ++// CONSTDATA date::month June{6}; ++// CONSTDATA date::month July{7}; ++// CONSTDATA date::month August{8}; ++// CONSTDATA date::month September{9}; ++// CONSTDATA date::month October{10}; ++// CONSTDATA date::month November{11}; ++// CONSTDATA date::month December{12}; ++// ++// CONSTDATA date::weekday Sunday{0u}; ++// CONSTDATA date::weekday Monday{1u}; ++// CONSTDATA date::weekday Tuesday{2u}; ++// CONSTDATA date::weekday Wednesday{3u}; ++// CONSTDATA date::weekday Thursday{4u}; ++// CONSTDATA date::weekday Friday{5u}; ++// CONSTDATA date::weekday Saturday{6u}; ++ ++#if HAS_VOID_T ++ ++template > ++struct is_clock ++ : std::false_type ++{}; ++ ++template ++struct is_clock> ++ : std::true_type ++{}; ++ ++template inline constexpr bool is_clock_v = is_clock::value; ++ ++#endif // HAS_VOID_T ++ ++//----------------+ ++// Implementation | ++//----------------+ ++ ++// utilities ++namespace detail { ++ ++template> ++class save_istream ++{ ++protected: ++ std::basic_ios& is_; ++ CharT fill_; ++ std::ios::fmtflags flags_; ++ std::streamsize precision_; ++ std::streamsize width_; ++ std::basic_ostream* tie_; ++ std::locale loc_; ++ ++public: ++ ~save_istream() ++ { ++ is_.fill(fill_); ++ is_.flags(flags_); ++ is_.precision(precision_); ++ is_.width(width_); ++ is_.imbue(loc_); ++ is_.tie(tie_); ++ } ++ ++ save_istream(const save_istream&) = delete; ++ save_istream& operator=(const save_istream&) = delete; ++ ++ explicit save_istream(std::basic_ios& is) ++ : is_(is) ++ , fill_(is.fill()) ++ , flags_(is.flags()) ++ , precision_(is.precision()) ++ , width_(is.width(0)) ++ , tie_(is.tie(nullptr)) ++ , loc_(is.getloc()) ++ { ++ if (tie_ != nullptr) ++ tie_->flush(); ++ } ++}; ++ ++template> ++class save_ostream ++ : private save_istream ++{ ++public: ++ ~save_ostream() ++ { ++ if ((this->flags_ & std::ios::unitbuf) && ++#if HAS_UNCAUGHT_EXCEPTIONS ++ std::uncaught_exceptions() == 0 && ++#else ++ !std::uncaught_exception() && ++#endif ++ this->is_.good()) ++ this->is_.rdbuf()->pubsync(); ++ } ++ ++ save_ostream(const save_ostream&) = delete; ++ save_ostream& operator=(const save_ostream&) = delete; ++ ++ explicit save_ostream(std::basic_ios& os) ++ : save_istream(os) ++ { ++ } ++}; ++ ++template ++struct choose_trunc_type ++{ ++ static const int digits = std::numeric_limits::digits; ++ using type = typename std::conditional ++ < ++ digits < 32, ++ std::int32_t, ++ typename std::conditional ++ < ++ digits < 64, ++ std::int64_t, ++#ifdef __SIZEOF_INT128__ ++ __int128 ++#else ++ std::int64_t ++#endif ++ >::type ++ >::type; ++}; ++ ++template ++CONSTCD11 ++inline ++typename std::enable_if ++< ++ !std::chrono::treat_as_floating_point::value, ++ T ++>::type ++trunc(T t) NOEXCEPT ++{ ++ return t; ++} ++ ++template ++CONSTCD14 ++inline ++typename std::enable_if ++< ++ std::chrono::treat_as_floating_point::value, ++ T ++>::type ++trunc(T t) NOEXCEPT ++{ ++ using std::numeric_limits; ++ using I = typename choose_trunc_type::type; ++ CONSTDATA auto digits = numeric_limits::digits; ++ static_assert(digits < numeric_limits::digits, ""); ++ CONSTDATA auto max = I{1} << (digits-1); ++ CONSTDATA auto min = -max; ++ const auto negative = t < T{0}; ++ if (min <= t && t <= max && t != 0 && t == t) ++ { ++ t = static_cast(static_cast(t)); ++ if (t == 0 && negative) ++ t = -t; ++ } ++ return t; ++} ++ ++template ++struct static_gcd ++{ ++ static const std::intmax_t value = static_gcd::value; ++}; ++ ++template ++struct static_gcd ++{ ++ static const std::intmax_t value = Xp; ++}; ++ ++template <> ++struct static_gcd<0, 0> ++{ ++ static const std::intmax_t value = 1; ++}; ++ ++template ++struct no_overflow ++{ ++private: ++ static const std::intmax_t gcd_n1_n2 = static_gcd::value; ++ static const std::intmax_t gcd_d1_d2 = static_gcd::value; ++ static const std::intmax_t n1 = R1::num / gcd_n1_n2; ++ static const std::intmax_t d1 = R1::den / gcd_d1_d2; ++ static const std::intmax_t n2 = R2::num / gcd_n1_n2; ++ static const std::intmax_t d2 = R2::den / gcd_d1_d2; ++#ifdef __cpp_constexpr ++ static const std::intmax_t max = std::numeric_limits::max(); ++#else ++ static const std::intmax_t max = LLONG_MAX; ++#endif ++ ++ template ++ struct mul // overflow == false ++ { ++ static const std::intmax_t value = Xp * Yp; ++ }; ++ ++ template ++ struct mul ++ { ++ static const std::intmax_t value = 1; ++ }; ++ ++public: ++ static const bool value = (n1 <= max / d2) && (n2 <= max / d1); ++ typedef std::ratio::value, ++ mul::value> type; ++}; ++ ++} // detail ++ ++// trunc towards zero ++template ++CONSTCD11 ++inline ++typename std::enable_if ++< ++ detail::no_overflow::value, ++ To ++>::type ++trunc(const std::chrono::duration& d) ++{ ++ return To{detail::trunc(std::chrono::duration_cast(d).count())}; ++} ++ ++template ++CONSTCD11 ++inline ++typename std::enable_if ++< ++ !detail::no_overflow::value, ++ To ++>::type ++trunc(const std::chrono::duration& d) ++{ ++ using std::chrono::duration_cast; ++ using std::chrono::duration; ++ using rep = typename std::common_type::type; ++ return To{detail::trunc(duration_cast(duration_cast>(d)).count())}; ++} ++ ++#ifndef HAS_CHRONO_ROUNDING ++# if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__))) ++# define HAS_CHRONO_ROUNDING 1 ++# elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510 ++# define HAS_CHRONO_ROUNDING 1 ++# elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800 ++# define HAS_CHRONO_ROUNDING 1 ++# else ++# define HAS_CHRONO_ROUNDING 0 ++# endif ++#endif // HAS_CHRONO_ROUNDING ++ ++#if HAS_CHRONO_ROUNDING == 0 ++ ++// round down ++template ++CONSTCD14 ++inline ++typename std::enable_if ++< ++ detail::no_overflow::value, ++ To ++>::type ++floor(const std::chrono::duration& d) ++{ ++ auto t = trunc(d); ++ if (t > d) ++ return t - To{1}; ++ return t; ++} ++ ++template ++CONSTCD14 ++inline ++typename std::enable_if ++< ++ !detail::no_overflow::value, ++ To ++>::type ++floor(const std::chrono::duration& d) ++{ ++ using rep = typename std::common_type::type; ++ return floor(floor>(d)); ++} ++ ++// round to nearest, to even on tie ++template ++CONSTCD14 ++inline ++To ++round(const std::chrono::duration& d) ++{ ++ auto t0 = floor(d); ++ auto t1 = t0 + To{1}; ++ if (t1 == To{0} && t0 < To{0}) ++ t1 = -t1; ++ auto diff0 = d - t0; ++ auto diff1 = t1 - d; ++ if (diff0 == diff1) ++ { ++ if (t0 - trunc(t0/2)*2 == To{0}) ++ return t0; ++ return t1; ++ } ++ if (diff0 < diff1) ++ return t0; ++ return t1; ++} ++ ++// round up ++template ++CONSTCD14 ++inline ++To ++ceil(const std::chrono::duration& d) ++{ ++ auto t = trunc(d); ++ if (t < d) ++ return t + To{1}; ++ return t; ++} ++ ++template ::is_signed ++ >::type> ++CONSTCD11 ++std::chrono::duration ++abs(std::chrono::duration d) ++{ ++ return d >= d.zero() ? d : static_cast(-d); ++} ++ ++// round down ++template ++CONSTCD11 ++inline ++std::chrono::time_point ++floor(const std::chrono::time_point& tp) ++{ ++ using std::chrono::time_point; ++ return time_point{date::floor(tp.time_since_epoch())}; ++} ++ ++// round to nearest, to even on tie ++template ++CONSTCD11 ++inline ++std::chrono::time_point ++round(const std::chrono::time_point& tp) ++{ ++ using std::chrono::time_point; ++ return time_point{round(tp.time_since_epoch())}; ++} ++ ++// round up ++template ++CONSTCD11 ++inline ++std::chrono::time_point ++ceil(const std::chrono::time_point& tp) ++{ ++ using std::chrono::time_point; ++ return time_point{ceil(tp.time_since_epoch())}; ++} ++ ++#else // HAS_CHRONO_ROUNDING == 1 ++ ++using std::chrono::floor; ++using std::chrono::ceil; ++using std::chrono::round; ++using std::chrono::abs; ++ ++#endif // HAS_CHRONO_ROUNDING ++ ++namespace detail ++{ ++ ++template ++CONSTCD14 ++inline ++typename std::enable_if ++< ++ !std::chrono::treat_as_floating_point::value, ++ To ++>::type ++round_i(const std::chrono::duration& d) ++{ ++ return round(d); ++} ++ ++template ++CONSTCD14 ++inline ++typename std::enable_if ++< ++ std::chrono::treat_as_floating_point::value, ++ To ++>::type ++round_i(const std::chrono::duration& d) ++{ ++ return d; ++} ++ ++template ++CONSTCD11 ++inline ++std::chrono::time_point ++round_i(const std::chrono::time_point& tp) ++{ ++ using std::chrono::time_point; ++ return time_point{round_i(tp.time_since_epoch())}; ++} ++ ++} // detail ++ ++// trunc towards zero ++template ++CONSTCD11 ++inline ++std::chrono::time_point ++trunc(const std::chrono::time_point& tp) ++{ ++ using std::chrono::time_point; ++ return time_point{trunc(tp.time_since_epoch())}; ++} ++ ++// day ++ ++CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast(d)) {} ++CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;} ++CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ++CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;} ++CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ++CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;} ++CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;} ++CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;} ++CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;} ++ ++CONSTCD11 ++inline ++bool ++operator==(const day& x, const day& y) NOEXCEPT ++{ ++ return static_cast(x) == static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const day& x, const day& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const day& x, const day& y) NOEXCEPT ++{ ++ return static_cast(x) < static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const day& x, const day& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const day& x, const day& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const day& x, const day& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++CONSTCD11 ++inline ++days ++operator-(const day& x, const day& y) NOEXCEPT ++{ ++ return days{static_cast(static_cast(x) ++ - static_cast(y))}; ++} ++ ++CONSTCD11 ++inline ++day ++operator+(const day& x, const days& y) NOEXCEPT ++{ ++ return day{static_cast(x) + static_cast(y.count())}; ++} ++ ++CONSTCD11 ++inline ++day ++operator+(const days& x, const day& y) NOEXCEPT ++{ ++ return y + x; ++} ++ ++CONSTCD11 ++inline ++day ++operator-(const day& x, const days& y) NOEXCEPT ++{ ++ return x + -y; ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const day& d) ++{ ++ detail::save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << static_cast(d); ++ return os; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const day& d) ++{ ++ detail::low_level_fmt(os, d); ++ if (!d.ok()) ++ os << " is not a valid day"; ++ return os; ++} ++ ++// month ++ ++CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast(m)) {} ++CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;} ++CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ++CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;} ++CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ++ ++CONSTCD14 ++inline ++month& ++month::operator+=(const months& m) NOEXCEPT ++{ ++ *this = *this + m; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++month& ++month::operator-=(const months& m) NOEXCEPT ++{ ++ *this = *this - m; ++ return *this; ++} ++ ++CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;} ++CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;} ++ ++CONSTCD11 ++inline ++bool ++operator==(const month& x, const month& y) NOEXCEPT ++{ ++ return static_cast(x) == static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const month& x, const month& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const month& x, const month& y) NOEXCEPT ++{ ++ return static_cast(x) < static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const month& x, const month& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const month& x, const month& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const month& x, const month& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++CONSTCD14 ++inline ++months ++operator-(const month& x, const month& y) NOEXCEPT ++{ ++ auto const d = static_cast(x) - static_cast(y); ++ return months(d <= 11 ? d : d + 12); ++} ++ ++CONSTCD14 ++inline ++month ++operator+(const month& x, const months& y) NOEXCEPT ++{ ++ auto const mu = static_cast(static_cast(x)) + y.count() - 1; ++ auto const yr = (mu >= 0 ? mu : mu-11) / 12; ++ return month{static_cast(mu - yr * 12 + 1)}; ++} ++ ++CONSTCD14 ++inline ++month ++operator+(const months& x, const month& y) NOEXCEPT ++{ ++ return y + x; ++} ++ ++CONSTCD14 ++inline ++month ++operator-(const month& x, const months& y) NOEXCEPT ++{ ++ return x + -y; ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const month& m) ++{ ++ if (m.ok()) ++ { ++ CharT fmt[] = {'%', 'b', 0}; ++ os << format(os.getloc(), fmt, m); ++ } ++ else ++ os << static_cast(m); ++ return os; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month& m) ++{ ++ detail::low_level_fmt(os, m); ++ if (!m.ok()) ++ os << " is not a valid month"; ++ return os; ++} ++ ++// year ++ ++CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} ++CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;} ++CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ++CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;} ++CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ++CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} ++CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} ++CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};} ++CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;} ++ ++CONSTCD11 ++inline ++bool ++year::is_leap() const NOEXCEPT ++{ ++ return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0); ++} ++ ++CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} ++ ++CONSTCD11 ++inline ++bool ++year::ok() const NOEXCEPT ++{ ++ return y_ != std::numeric_limits::min(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year& x, const year& y) NOEXCEPT ++{ ++ return static_cast(x) == static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year& x, const year& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const year& x, const year& y) NOEXCEPT ++{ ++ return static_cast(x) < static_cast(y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const year& x, const year& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const year& x, const year& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const year& x, const year& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++CONSTCD11 ++inline ++years ++operator-(const year& x, const year& y) NOEXCEPT ++{ ++ return years{static_cast(x) - static_cast(y)}; ++} ++ ++CONSTCD11 ++inline ++year ++operator+(const year& x, const years& y) NOEXCEPT ++{ ++ return year{static_cast(x) + y.count()}; ++} ++ ++CONSTCD11 ++inline ++year ++operator+(const years& x, const year& y) NOEXCEPT ++{ ++ return y + x; ++} ++ ++CONSTCD11 ++inline ++year ++operator-(const year& x, const years& y) NOEXCEPT ++{ ++ return year{static_cast(x) - y.count()}; ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const year& y) ++{ ++ detail::save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::internal); ++ os.width(4 + (y < year{0})); ++ os.imbue(std::locale::classic()); ++ os << static_cast(y); ++ return os; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year& y) ++{ ++ detail::low_level_fmt(os, y); ++ if (!y.ok()) ++ os << " is not a valid year"; ++ return os; ++} ++ ++// weekday ++ ++CONSTCD14 ++inline ++unsigned char ++weekday::weekday_from_days(int z) NOEXCEPT ++{ ++ auto u = static_cast(z); ++ return static_cast(z >= -4 ? (u+4) % 7 : u % 7); ++} ++ ++CONSTCD11 ++inline ++weekday::weekday(unsigned wd) NOEXCEPT ++ : wd_(static_cast(wd != 7 ? wd : 0)) ++ {} ++ ++CONSTCD14 ++inline ++weekday::weekday(const sys_days& dp) NOEXCEPT ++ : wd_(weekday_from_days(dp.time_since_epoch().count())) ++ {} ++ ++CONSTCD14 ++inline ++weekday::weekday(const local_days& dp) NOEXCEPT ++ : wd_(weekday_from_days(dp.time_since_epoch().count())) ++ {} ++ ++CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;} ++CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ++CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;} ++CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ++ ++CONSTCD14 ++inline ++weekday& ++weekday::operator+=(const days& d) NOEXCEPT ++{ ++ *this = *this + d; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++weekday& ++weekday::operator-=(const days& d) NOEXCEPT ++{ ++ *this = *this - d; ++ return *this; ++} ++ ++CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} ++ ++CONSTCD11 ++inline ++unsigned weekday::c_encoding() const NOEXCEPT ++{ ++ return unsigned{wd_}; ++} ++ ++CONSTCD11 ++inline ++unsigned weekday::iso_encoding() const NOEXCEPT ++{ ++ return unsigned{((wd_ == 0u) ? 7u : wd_)}; ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const weekday& x, const weekday& y) NOEXCEPT ++{ ++ return x.wd_ == y.wd_; ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const weekday& x, const weekday& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD14 ++inline ++days ++operator-(const weekday& x, const weekday& y) NOEXCEPT ++{ ++ auto const wdu = x.wd_ - y.wd_; ++ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; ++ return days{wdu - wk * 7}; ++} ++ ++CONSTCD14 ++inline ++weekday ++operator+(const weekday& x, const days& y) NOEXCEPT ++{ ++ auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); ++ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; ++ return weekday{static_cast(wdu - wk * 7)}; ++} ++ ++CONSTCD14 ++inline ++weekday ++operator+(const days& x, const weekday& y) NOEXCEPT ++{ ++ return y + x; ++} ++ ++CONSTCD14 ++inline ++weekday ++operator-(const weekday& x, const days& y) NOEXCEPT ++{ ++ return x + -y; ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const weekday& wd) ++{ ++ if (wd.ok()) ++ { ++ CharT fmt[] = {'%', 'a', 0}; ++ os << format(fmt, wd); ++ } ++ else ++ os << wd.c_encoding(); ++ return os; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday& wd) ++{ ++ detail::low_level_fmt(os, wd); ++ if (!wd.ok()) ++ os << " is not a valid weekday"; ++ return os; ++} ++ ++#if !defined(_MSC_VER) || (_MSC_VER >= 1900) ++inline namespace literals ++{ ++ ++CONSTCD11 ++inline ++date::day ++operator "" _d(unsigned long long d) NOEXCEPT ++{ ++ return date::day{static_cast(d)}; ++} ++ ++CONSTCD11 ++inline ++date::year ++operator "" _y(unsigned long long y) NOEXCEPT ++{ ++ return date::year(static_cast(y)); ++} ++#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) ++ ++CONSTDATA date::last_spec last{}; ++ ++CONSTDATA date::month jan{1}; ++CONSTDATA date::month feb{2}; ++CONSTDATA date::month mar{3}; ++CONSTDATA date::month apr{4}; ++CONSTDATA date::month may{5}; ++CONSTDATA date::month jun{6}; ++CONSTDATA date::month jul{7}; ++CONSTDATA date::month aug{8}; ++CONSTDATA date::month sep{9}; ++CONSTDATA date::month oct{10}; ++CONSTDATA date::month nov{11}; ++CONSTDATA date::month dec{12}; ++ ++CONSTDATA date::weekday sun{0u}; ++CONSTDATA date::weekday mon{1u}; ++CONSTDATA date::weekday tue{2u}; ++CONSTDATA date::weekday wed{3u}; ++CONSTDATA date::weekday thu{4u}; ++CONSTDATA date::weekday fri{5u}; ++CONSTDATA date::weekday sat{6u}; ++ ++#if !defined(_MSC_VER) || (_MSC_VER >= 1900) ++} // inline namespace literals ++#endif ++ ++CONSTDATA date::month January{1}; ++CONSTDATA date::month February{2}; ++CONSTDATA date::month March{3}; ++CONSTDATA date::month April{4}; ++CONSTDATA date::month May{5}; ++CONSTDATA date::month June{6}; ++CONSTDATA date::month July{7}; ++CONSTDATA date::month August{8}; ++CONSTDATA date::month September{9}; ++CONSTDATA date::month October{10}; ++CONSTDATA date::month November{11}; ++CONSTDATA date::month December{12}; ++ ++CONSTDATA date::weekday Monday{1}; ++CONSTDATA date::weekday Tuesday{2}; ++CONSTDATA date::weekday Wednesday{3}; ++CONSTDATA date::weekday Thursday{4}; ++CONSTDATA date::weekday Friday{5}; ++CONSTDATA date::weekday Saturday{6}; ++CONSTDATA date::weekday Sunday{7}; ++ ++// weekday_indexed ++ ++CONSTCD11 ++inline ++weekday ++weekday_indexed::weekday() const NOEXCEPT ++{ ++ return date::weekday{static_cast(wd_)}; ++} ++ ++CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;} ++ ++CONSTCD11 ++inline ++bool ++weekday_indexed::ok() const NOEXCEPT ++{ ++ return weekday().ok() && 1 <= index_ && index_ <= 5; ++} ++ ++#ifdef __GNUC__ ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wconversion" ++#endif // __GNUC__ ++ ++CONSTCD11 ++inline ++weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT ++ : wd_(static_cast(static_cast(wd.wd_))) ++ , index_(static_cast(index)) ++ {} ++ ++#ifdef __GNUC__ ++# pragma GCC diagnostic pop ++#endif // __GNUC__ ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const weekday_indexed& wdi) ++{ ++ return low_level_fmt(os, wdi.weekday()) << '[' << wdi.index() << ']'; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday_indexed& wdi) ++{ ++ detail::low_level_fmt(os, wdi); ++ if (!wdi.ok()) ++ os << " is not a valid weekday_indexed"; ++ return os; ++} ++ ++CONSTCD11 ++inline ++weekday_indexed ++weekday::operator[](unsigned index) const NOEXCEPT ++{ ++ return {*this, index}; ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT ++{ ++ return x.weekday() == y.weekday() && x.index() == y.index(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++// weekday_last ++ ++CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;} ++CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();} ++CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {} ++ ++CONSTCD11 ++inline ++bool ++operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT ++{ ++ return x.weekday() == y.weekday(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const weekday_last& wdl) ++{ ++ return low_level_fmt(os, wdl.weekday()) << "[last]"; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const weekday_last& wdl) ++{ ++ detail::low_level_fmt(os, wdl); ++ if (!wdl.ok()) ++ os << " is not a valid weekday_last"; ++ return os; ++} ++ ++CONSTCD11 ++inline ++weekday_last ++weekday::operator[](last_spec) const NOEXCEPT ++{ ++ return weekday_last{*this}; ++} ++ ++// year_month ++ ++CONSTCD11 ++inline ++year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT ++ : y_(y) ++ , m_(m) ++ {} ++ ++CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;} ++CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;} ++CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();} ++ ++template ++CONSTCD14 ++inline ++year_month& ++year_month::operator+=(const months& dm) NOEXCEPT ++{ ++ *this = *this + dm; ++ return *this; ++} ++ ++template ++CONSTCD14 ++inline ++year_month& ++year_month::operator-=(const months& dm) NOEXCEPT ++{ ++ *this = *this - dm; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month& ++year_month::operator+=(const years& dy) NOEXCEPT ++{ ++ *this = *this + dy; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month& ++year_month::operator-=(const years& dy) NOEXCEPT ++{ ++ *this = *this - dy; ++ return *this; ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return x.year() == y.year() && x.month() == y.month(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return x.year() < y.year() ? true ++ : (x.year() > y.year() ? false ++ : (x.month() < y.month())); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++template ++CONSTCD14 ++inline ++year_month ++operator+(const year_month& ym, const months& dm) NOEXCEPT ++{ ++ auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); ++ auto dy = (dmi >= 0 ? dmi : dmi-11) / 12; ++ dmi = dmi - dy * 12 + 1; ++ return (ym.year() + years(dy)) / month(static_cast(dmi)); ++} ++ ++template ++CONSTCD14 ++inline ++year_month ++operator+(const months& dm, const year_month& ym) NOEXCEPT ++{ ++ return ym + dm; ++} ++ ++template ++CONSTCD14 ++inline ++year_month ++operator-(const year_month& ym, const months& dm) NOEXCEPT ++{ ++ return ym + -dm; ++} ++ ++CONSTCD11 ++inline ++months ++operator-(const year_month& x, const year_month& y) NOEXCEPT ++{ ++ return (x.year() - y.year()) + ++ months(static_cast(x.month()) - static_cast(y.month())); ++} ++ ++CONSTCD11 ++inline ++year_month ++operator+(const year_month& ym, const years& dy) NOEXCEPT ++{ ++ return (ym.year() + dy) / ym.month(); ++} ++ ++CONSTCD11 ++inline ++year_month ++operator+(const years& dy, const year_month& ym) NOEXCEPT ++{ ++ return ym + dy; ++} ++ ++CONSTCD11 ++inline ++year_month ++operator-(const year_month& ym, const years& dy) NOEXCEPT ++{ ++ return ym + -dy; ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const year_month& ym) ++{ ++ low_level_fmt(os, ym.year()) << '/'; ++ return low_level_fmt(os, ym.month()); ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month& ym) ++{ ++ detail::low_level_fmt(os, ym); ++ if (!ym.ok()) ++ os << " is not a valid year_month"; ++ return os; ++} ++ ++// month_day ++ ++CONSTCD11 ++inline ++month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT ++ : m_(m) ++ , d_(d) ++ {} ++ ++CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;} ++CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;} ++ ++CONSTCD14 ++inline ++bool ++month_day::ok() const NOEXCEPT ++{ ++ CONSTDATA date::day d[] = ++ { ++ date::day(31), date::day(29), date::day(31), ++ date::day(30), date::day(31), date::day(30), ++ date::day(31), date::day(31), date::day(30), ++ date::day(31), date::day(30), date::day(31) ++ }; ++ return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast(m_)-1]; ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return x.month() == y.month() && x.day() == y.day(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return x.month() < y.month() ? true ++ : (x.month() > y.month() ? false ++ : (x.day() < y.day())); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const month_day& x, const month_day& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const month_day& md) ++{ ++ low_level_fmt(os, md.month()) << '/'; ++ return low_level_fmt(os, md.day()); ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_day& md) ++{ ++ detail::low_level_fmt(os, md); ++ if (!md.ok()) ++ os << " is not a valid month_day"; ++ return os; ++} ++ ++// month_day_last ++ ++CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;} ++CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();} ++CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {} ++ ++CONSTCD11 ++inline ++bool ++operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return x.month() == y.month(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return x.month() < y.month(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const month_day_last& mdl) ++{ ++ return low_level_fmt(os, mdl.month()) << "/last"; ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_day_last& mdl) ++{ ++ detail::low_level_fmt(os, mdl); ++ if (!mdl.ok()) ++ os << " is not a valid month_day_last"; ++ return os; ++} ++ ++// month_weekday ++ ++CONSTCD11 ++inline ++month_weekday::month_weekday(const date::month& m, ++ const date::weekday_indexed& wdi) NOEXCEPT ++ : m_(m) ++ , wdi_(wdi) ++ {} ++ ++CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;} ++ ++CONSTCD11 ++inline ++weekday_indexed ++month_weekday::weekday_indexed() const NOEXCEPT ++{ ++ return wdi_; ++} ++ ++CONSTCD11 ++inline ++bool ++month_weekday::ok() const NOEXCEPT ++{ ++ return m_.ok() && wdi_.ok(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT ++{ ++ return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const month_weekday& mwd) ++{ ++ low_level_fmt(os, mwd.month()) << '/'; ++ return low_level_fmt(os, mwd.weekday_indexed()); ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_weekday& mwd) ++{ ++ detail::low_level_fmt(os, mwd); ++ if (!mwd.ok()) ++ os << " is not a valid month_weekday"; ++ return os; ++} ++ ++// month_weekday_last ++ ++CONSTCD11 ++inline ++month_weekday_last::month_weekday_last(const date::month& m, ++ const date::weekday_last& wdl) NOEXCEPT ++ : m_(m) ++ , wdl_(wdl) ++ {} ++ ++CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;} ++ ++CONSTCD11 ++inline ++weekday_last ++month_weekday_last::weekday_last() const NOEXCEPT ++{ ++ return wdl_; ++} ++ ++CONSTCD11 ++inline ++bool ++month_weekday_last::ok() const NOEXCEPT ++{ ++ return m_.ok() && wdl_.ok(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT ++{ ++ return x.month() == y.month() && x.weekday_last() == y.weekday_last(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const month_weekday_last& mwdl) ++{ ++ low_level_fmt(os, mwdl.month()) << '/'; ++ return low_level_fmt(os, mwdl.weekday_last()); ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const month_weekday_last& mwdl) ++{ ++ detail::low_level_fmt(os, mwdl); ++ if (!mwdl.ok()) ++ os << " is not a valid month_weekday_last"; ++ return os; ++} ++ ++// year_month_day_last ++ ++CONSTCD11 ++inline ++year_month_day_last::year_month_day_last(const date::year& y, ++ const date::month_day_last& mdl) NOEXCEPT ++ : y_(y) ++ , mdl_(mdl) ++ {} ++ ++template ++CONSTCD14 ++inline ++year_month_day_last& ++year_month_day_last::operator+=(const months& m) NOEXCEPT ++{ ++ *this = *this + m; ++ return *this; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day_last& ++year_month_day_last::operator-=(const months& m) NOEXCEPT ++{ ++ *this = *this - m; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_day_last& ++year_month_day_last::operator+=(const years& y) NOEXCEPT ++{ ++ *this = *this + y; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_day_last& ++year_month_day_last::operator-=(const years& y) NOEXCEPT ++{ ++ *this = *this - y; ++ return *this; ++} ++ ++CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;} ++CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();} ++ ++CONSTCD11 ++inline ++month_day_last ++year_month_day_last::month_day_last() const NOEXCEPT ++{ ++ return mdl_; ++} ++ ++CONSTCD14 ++inline ++day ++year_month_day_last::day() const NOEXCEPT ++{ ++ CONSTDATA date::day d[] = ++ { ++ date::day(31), date::day(28), date::day(31), ++ date::day(30), date::day(31), date::day(30), ++ date::day(31), date::day(31), date::day(30), ++ date::day(31), date::day(30), date::day(31) ++ }; ++ return (month() != February || !y_.is_leap()) && mdl_.ok() ? ++ d[static_cast(month()) - 1] : date::day{29}; ++} ++ ++CONSTCD14 ++inline ++year_month_day_last::operator sys_days() const NOEXCEPT ++{ ++ return sys_days(year()/month()/day()); ++} ++ ++CONSTCD14 ++inline ++year_month_day_last::operator local_days() const NOEXCEPT ++{ ++ return local_days(year()/month()/day()); ++} ++ ++CONSTCD11 ++inline ++bool ++year_month_day_last::ok() const NOEXCEPT ++{ ++ return y_.ok() && mdl_.ok(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return x.year() == y.year() && x.month_day_last() == y.month_day_last(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return x.year() < y.year() ? true ++ : (x.year() > y.year() ? false ++ : (x.month_day_last() < y.month_day_last())); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++namespace detail ++{ ++ ++template ++std::basic_ostream& ++low_level_fmt(std::basic_ostream& os, const year_month_day_last& ymdl) ++{ ++ low_level_fmt(os, ymdl.year()) << '/'; ++ return low_level_fmt(os, ymdl.month_day_last()); ++} ++ ++} // namespace detail ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_day_last& ymdl) ++{ ++ detail::low_level_fmt(os, ymdl); ++ if (!ymdl.ok()) ++ os << " is not a valid year_month_day_last"; ++ return os; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day_last ++operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT ++{ ++ return (ymdl.year() / ymdl.month() + dm) / last; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day_last ++operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT ++{ ++ return ymdl + dm; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day_last ++operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT ++{ ++ return ymdl + (-dm); ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT ++{ ++ return {ymdl.year()+dy, ymdl.month_day_last()}; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT ++{ ++ return ymdl + dy; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT ++{ ++ return ymdl + (-dy); ++} ++ ++// year_month_day ++ ++CONSTCD11 ++inline ++year_month_day::year_month_day(const date::year& y, const date::month& m, ++ const date::day& d) NOEXCEPT ++ : y_(y) ++ , m_(m) ++ , d_(d) ++ {} ++ ++CONSTCD14 ++inline ++year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT ++ : y_(ymdl.year()) ++ , m_(ymdl.month()) ++ , d_(ymdl.day()) ++ {} ++ ++CONSTCD14 ++inline ++year_month_day::year_month_day(sys_days dp) NOEXCEPT ++ : year_month_day(from_days(dp.time_since_epoch())) ++ {} ++ ++CONSTCD14 ++inline ++year_month_day::year_month_day(local_days dp) NOEXCEPT ++ : year_month_day(from_days(dp.time_since_epoch())) ++ {} ++ ++CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;} ++CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;} ++CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;} ++ ++template ++CONSTCD14 ++inline ++year_month_day& ++year_month_day::operator+=(const months& m) NOEXCEPT ++{ ++ *this = *this + m; ++ return *this; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day& ++year_month_day::operator-=(const months& m) NOEXCEPT ++{ ++ *this = *this - m; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_day& ++year_month_day::operator+=(const years& y) NOEXCEPT ++{ ++ *this = *this + y; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_day& ++year_month_day::operator-=(const years& y) NOEXCEPT ++{ ++ *this = *this - y; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++days ++year_month_day::to_days() const NOEXCEPT ++{ ++ static_assert(std::numeric_limits::digits >= 18, ++ "This algorithm has not been ported to a 16 bit unsigned integer"); ++ static_assert(std::numeric_limits::digits >= 20, ++ "This algorithm has not been ported to a 16 bit signed integer"); ++ auto const y = static_cast(y_) - (m_ <= February); ++ auto const m = static_cast(m_); ++ auto const d = static_cast(d_); ++ auto const era = (y >= 0 ? y : y-399) / 400; ++ auto const yoe = static_cast(y - era * 400); // [0, 399] ++ auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365] ++ auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] ++ return days{era * 146097 + static_cast(doe) - 719468}; ++} ++ ++CONSTCD14 ++inline ++year_month_day::operator sys_days() const NOEXCEPT ++{ ++ return sys_days{to_days()}; ++} ++ ++CONSTCD14 ++inline ++year_month_day::operator local_days() const NOEXCEPT ++{ ++ return local_days{to_days()}; ++} ++ ++CONSTCD14 ++inline ++bool ++year_month_day::ok() const NOEXCEPT ++{ ++ if (!(y_.ok() && m_.ok())) ++ return false; ++ return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++CONSTCD11 ++inline ++bool ++operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return x.year() < y.year() ? true ++ : (x.year() > y.year() ? false ++ : (x.month() < y.month() ? true ++ : (x.month() > y.month() ? false ++ : (x.day() < y.day())))); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return y < x; ++} ++ ++CONSTCD11 ++inline ++bool ++operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return !(y < x); ++} ++ ++CONSTCD11 ++inline ++bool ++operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT ++{ ++ return !(x < y); ++} ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_day& ymd) ++{ ++ detail::save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.imbue(std::locale::classic()); ++ os << static_cast(ymd.year()) << '-'; ++ os.width(2); ++ os << static_cast(ymd.month()) << '-'; ++ os.width(2); ++ os << static_cast(ymd.day()); ++ if (!ymd.ok()) ++ os << " is not a valid year_month_day"; ++ return os; ++} ++ ++CONSTCD14 ++inline ++year_month_day ++year_month_day::from_days(days dp) NOEXCEPT ++{ ++ static_assert(std::numeric_limits::digits >= 18, ++ "This algorithm has not been ported to a 16 bit unsigned integer"); ++ static_assert(std::numeric_limits::digits >= 20, ++ "This algorithm has not been ported to a 16 bit signed integer"); ++ auto const z = dp.count() + 719468; ++ auto const era = (z >= 0 ? z : z - 146096) / 146097; ++ auto const doe = static_cast(z - era * 146097); // [0, 146096] ++ auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] ++ auto const y = static_cast(yoe) + era * 400; ++ auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] ++ auto const mp = (5*doy + 2)/153; // [0, 11] ++ auto const d = doy - (153*mp+2)/5 + 1; // [1, 31] ++ auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12] ++ return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)}; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day ++operator+(const year_month_day& ymd, const months& dm) NOEXCEPT ++{ ++ return (ymd.year() / ymd.month() + dm) / ymd.day(); ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day ++operator+(const months& dm, const year_month_day& ymd) NOEXCEPT ++{ ++ return ymd + dm; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_day ++operator-(const year_month_day& ymd, const months& dm) NOEXCEPT ++{ ++ return ymd + (-dm); ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator+(const year_month_day& ymd, const years& dy) NOEXCEPT ++{ ++ return (ymd.year() + dy) / ymd.month() / ymd.day(); ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator+(const years& dy, const year_month_day& ymd) NOEXCEPT ++{ ++ return ymd + dy; ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator-(const year_month_day& ymd, const years& dy) NOEXCEPT ++{ ++ return ymd + (-dy); ++} ++ ++// year_month_weekday ++ ++CONSTCD11 ++inline ++year_month_weekday::year_month_weekday(const date::year& y, const date::month& m, ++ const date::weekday_indexed& wdi) ++ NOEXCEPT ++ : y_(y) ++ , m_(m) ++ , wdi_(wdi) ++ {} ++ ++CONSTCD14 ++inline ++year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT ++ : year_month_weekday(from_days(dp.time_since_epoch())) ++ {} ++ ++CONSTCD14 ++inline ++year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT ++ : year_month_weekday(from_days(dp.time_since_epoch())) ++ {} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday& ++year_month_weekday::operator+=(const months& m) NOEXCEPT ++{ ++ *this = *this + m; ++ return *this; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday& ++year_month_weekday::operator-=(const months& m) NOEXCEPT ++{ ++ *this = *this - m; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday& ++year_month_weekday::operator+=(const years& y) NOEXCEPT ++{ ++ *this = *this + y; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday& ++year_month_weekday::operator-=(const years& y) NOEXCEPT ++{ ++ *this = *this - y; ++ return *this; ++} ++ ++CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;} ++CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;} ++ ++CONSTCD11 ++inline ++weekday ++year_month_weekday::weekday() const NOEXCEPT ++{ ++ return wdi_.weekday(); ++} ++ ++CONSTCD11 ++inline ++unsigned ++year_month_weekday::index() const NOEXCEPT ++{ ++ return wdi_.index(); ++} ++ ++CONSTCD11 ++inline ++weekday_indexed ++year_month_weekday::weekday_indexed() const NOEXCEPT ++{ ++ return wdi_; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday::operator sys_days() const NOEXCEPT ++{ ++ return sys_days{to_days()}; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday::operator local_days() const NOEXCEPT ++{ ++ return local_days{to_days()}; ++} ++ ++CONSTCD14 ++inline ++bool ++year_month_weekday::ok() const NOEXCEPT ++{ ++ if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) ++ return false; ++ if (wdi_.index() <= 4) ++ return true; ++ auto d2 = wdi_.weekday() - date::weekday(static_cast(y_/m_/1)) + ++ days((wdi_.index()-1)*7 + 1); ++ return static_cast(d2.count()) <= static_cast((y_/m_/last).day()); ++} ++ ++CONSTCD14 ++inline ++year_month_weekday ++year_month_weekday::from_days(days d) NOEXCEPT ++{ ++ sys_days dp{d}; ++ auto const wd = date::weekday(dp); ++ auto const ymd = year_month_day(dp); ++ return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day())-1)/7+1]}; ++} ++ ++CONSTCD14 ++inline ++days ++year_month_weekday::to_days() const NOEXCEPT ++{ ++ auto d = sys_days(y_/m_/1); ++ return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7}) ++ ).time_since_epoch(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT ++{ ++ return x.year() == y.year() && x.month() == y.month() && ++ x.weekday_indexed() == y.weekday_indexed(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi) ++{ ++ detail::low_level_fmt(os, ymwdi.year()) << '/'; ++ detail::low_level_fmt(os, ymwdi.month()) << '/'; ++ detail::low_level_fmt(os, ymwdi.weekday_indexed()); ++ if (!ymwdi.ok()) ++ os << " is not a valid year_month_weekday"; ++ return os; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday ++operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT ++{ ++ return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday ++operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT ++{ ++ return ymwd + dm; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday ++operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT ++{ ++ return ymwd + (-dm); ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT ++{ ++ return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT ++{ ++ return ymwd + dy; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT ++{ ++ return ymwd + (-dy); ++} ++ ++// year_month_weekday_last ++ ++CONSTCD11 ++inline ++year_month_weekday_last::year_month_weekday_last(const date::year& y, ++ const date::month& m, ++ const date::weekday_last& wdl) NOEXCEPT ++ : y_(y) ++ , m_(m) ++ , wdl_(wdl) ++ {} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday_last& ++year_month_weekday_last::operator+=(const months& m) NOEXCEPT ++{ ++ *this = *this + m; ++ return *this; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday_last& ++year_month_weekday_last::operator-=(const months& m) NOEXCEPT ++{ ++ *this = *this - m; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday_last& ++year_month_weekday_last::operator+=(const years& y) NOEXCEPT ++{ ++ *this = *this + y; ++ return *this; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday_last& ++year_month_weekday_last::operator-=(const years& y) NOEXCEPT ++{ ++ *this = *this - y; ++ return *this; ++} ++ ++CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;} ++CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;} ++ ++CONSTCD11 ++inline ++weekday ++year_month_weekday_last::weekday() const NOEXCEPT ++{ ++ return wdl_.weekday(); ++} ++ ++CONSTCD11 ++inline ++weekday_last ++year_month_weekday_last::weekday_last() const NOEXCEPT ++{ ++ return wdl_; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday_last::operator sys_days() const NOEXCEPT ++{ ++ return sys_days{to_days()}; ++} ++ ++CONSTCD14 ++inline ++year_month_weekday_last::operator local_days() const NOEXCEPT ++{ ++ return local_days{to_days()}; ++} ++ ++CONSTCD11 ++inline ++bool ++year_month_weekday_last::ok() const NOEXCEPT ++{ ++ return y_.ok() && m_.ok() && wdl_.ok(); ++} ++ ++CONSTCD14 ++inline ++days ++year_month_weekday_last::to_days() const NOEXCEPT ++{ ++ auto const d = sys_days(y_/m_/last); ++ return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT ++{ ++ return x.year() == y.year() && x.month() == y.month() && ++ x.weekday_last() == y.weekday_last(); ++} ++ ++CONSTCD11 ++inline ++bool ++operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT ++{ ++ return !(x == y); ++} ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl) ++{ ++ detail::low_level_fmt(os, ymwdl.year()) << '/'; ++ detail::low_level_fmt(os, ymwdl.month()) << '/'; ++ detail::low_level_fmt(os, ymwdl.weekday_last()); ++ if (!ymwdl.ok()) ++ os << " is not a valid year_month_weekday_last"; ++ return os; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday_last ++operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT ++{ ++ return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday_last ++operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT ++{ ++ return ymwdl + dm; ++} ++ ++template ++CONSTCD14 ++inline ++year_month_weekday_last ++operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT ++{ ++ return ymwdl + (-dm); ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT ++{ ++ return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT ++{ ++ return ymwdl + dy; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT ++{ ++ return ymwdl + (-dy); ++} ++ ++// year_month from operator/() ++ ++CONSTCD11 ++inline ++year_month ++operator/(const year& y, const month& m) NOEXCEPT ++{ ++ return {y, m}; ++} ++ ++CONSTCD11 ++inline ++year_month ++operator/(const year& y, int m) NOEXCEPT ++{ ++ return y / month(static_cast(m)); ++} ++ ++// month_day from operator/() ++ ++CONSTCD11 ++inline ++month_day ++operator/(const month& m, const day& d) NOEXCEPT ++{ ++ return {m, d}; ++} ++ ++CONSTCD11 ++inline ++month_day ++operator/(const day& d, const month& m) NOEXCEPT ++{ ++ return m / d; ++} ++ ++CONSTCD11 ++inline ++month_day ++operator/(const month& m, int d) NOEXCEPT ++{ ++ return m / day(static_cast(d)); ++} ++ ++CONSTCD11 ++inline ++month_day ++operator/(int m, const day& d) NOEXCEPT ++{ ++ return month(static_cast(m)) / d; ++} ++ ++CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;} ++ ++// month_day_last from operator/() ++ ++CONSTCD11 ++inline ++month_day_last ++operator/(const month& m, last_spec) NOEXCEPT ++{ ++ return month_day_last{m}; ++} ++ ++CONSTCD11 ++inline ++month_day_last ++operator/(last_spec, const month& m) NOEXCEPT ++{ ++ return m/last; ++} ++ ++CONSTCD11 ++inline ++month_day_last ++operator/(int m, last_spec) NOEXCEPT ++{ ++ return month(static_cast(m))/last; ++} ++ ++CONSTCD11 ++inline ++month_day_last ++operator/(last_spec, int m) NOEXCEPT ++{ ++ return m/last; ++} ++ ++// month_weekday from operator/() ++ ++CONSTCD11 ++inline ++month_weekday ++operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT ++{ ++ return {m, wdi}; ++} ++ ++CONSTCD11 ++inline ++month_weekday ++operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT ++{ ++ return m / wdi; ++} ++ ++CONSTCD11 ++inline ++month_weekday ++operator/(int m, const weekday_indexed& wdi) NOEXCEPT ++{ ++ return month(static_cast(m)) / wdi; ++} ++ ++CONSTCD11 ++inline ++month_weekday ++operator/(const weekday_indexed& wdi, int m) NOEXCEPT ++{ ++ return m / wdi; ++} ++ ++// month_weekday_last from operator/() ++ ++CONSTCD11 ++inline ++month_weekday_last ++operator/(const month& m, const weekday_last& wdl) NOEXCEPT ++{ ++ return {m, wdl}; ++} ++ ++CONSTCD11 ++inline ++month_weekday_last ++operator/(const weekday_last& wdl, const month& m) NOEXCEPT ++{ ++ return m / wdl; ++} ++ ++CONSTCD11 ++inline ++month_weekday_last ++operator/(int m, const weekday_last& wdl) NOEXCEPT ++{ ++ return month(static_cast(m)) / wdl; ++} ++ ++CONSTCD11 ++inline ++month_weekday_last ++operator/(const weekday_last& wdl, int m) NOEXCEPT ++{ ++ return m / wdl; ++} ++ ++// year_month_day from operator/() ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(const year_month& ym, const day& d) NOEXCEPT ++{ ++ return {ym.year(), ym.month(), d}; ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(const year_month& ym, int d) NOEXCEPT ++{ ++ return ym / day(static_cast(d)); ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(const year& y, const month_day& md) NOEXCEPT ++{ ++ return y / md.month() / md.day(); ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(int y, const month_day& md) NOEXCEPT ++{ ++ return year(y) / md; ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(const month_day& md, const year& y) NOEXCEPT ++{ ++ return y / md; ++} ++ ++CONSTCD11 ++inline ++year_month_day ++operator/(const month_day& md, int y) NOEXCEPT ++{ ++ return year(y) / md; ++} ++ ++// year_month_day_last from operator/() ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator/(const year_month& ym, last_spec) NOEXCEPT ++{ ++ return {ym.year(), month_day_last{ym.month()}}; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator/(const year& y, const month_day_last& mdl) NOEXCEPT ++{ ++ return {y, mdl}; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator/(int y, const month_day_last& mdl) NOEXCEPT ++{ ++ return year(y) / mdl; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator/(const month_day_last& mdl, const year& y) NOEXCEPT ++{ ++ return y / mdl; ++} ++ ++CONSTCD11 ++inline ++year_month_day_last ++operator/(const month_day_last& mdl, int y) NOEXCEPT ++{ ++ return year(y) / mdl; ++} ++ ++// year_month_weekday from operator/() ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT ++{ ++ return {ym.year(), ym.month(), wdi}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator/(const year& y, const month_weekday& mwd) NOEXCEPT ++{ ++ return {y, mwd.month(), mwd.weekday_indexed()}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator/(int y, const month_weekday& mwd) NOEXCEPT ++{ ++ return year(y) / mwd; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator/(const month_weekday& mwd, const year& y) NOEXCEPT ++{ ++ return y / mwd; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday ++operator/(const month_weekday& mwd, int y) NOEXCEPT ++{ ++ return year(y) / mwd; ++} ++ ++// year_month_weekday_last from operator/() ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT ++{ ++ return {ym.year(), ym.month(), wdl}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT ++{ ++ return {y, mwdl.month(), mwdl.weekday_last()}; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator/(int y, const month_weekday_last& mwdl) NOEXCEPT ++{ ++ return year(y) / mwdl; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT ++{ ++ return y / mwdl; ++} ++ ++CONSTCD11 ++inline ++year_month_weekday_last ++operator/(const month_weekday_last& mwdl, int y) NOEXCEPT ++{ ++ return year(y) / mwdl; ++} ++ ++template ++struct fields; ++ ++template ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const fields& fds, const std::string* abbrev = nullptr, ++ const std::chrono::seconds* offset_sec = nullptr); ++ ++template ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ fields& fds, std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr); ++ ++// hh_mm_ss ++ ++namespace detail ++{ ++ ++struct undocumented {explicit undocumented() = default;}; ++ ++// width::value is the number of fractional decimal digits in 1/n ++// width<0>::value and width<1>::value are defined to be 0 ++// If 1/n takes more than 18 fractional decimal digits, ++// the result is truncated to 19. ++// Example: width<2>::value == 1 ++// Example: width<3>::value == 19 ++// Example: width<4>::value == 2 ++// Example: width<10>::value == 1 ++// Example: width<1000>::value == 3 ++template ++struct width ++{ ++ static_assert(d > 0, "width called with zero denominator"); ++ static CONSTDATA unsigned value = 1 + width::value; ++}; ++ ++template ++struct width ++{ ++ static CONSTDATA unsigned value = 0; ++}; ++ ++template ++struct static_pow10 ++{ ++private: ++ static CONSTDATA std::uint64_t h = static_pow10::value; ++public: ++ static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1); ++}; ++ ++template <> ++struct static_pow10<0> ++{ ++ static CONSTDATA std::uint64_t value = 1; ++}; ++ ++template ++class decimal_format_seconds ++{ ++ using CT = typename std::common_type::type; ++ using rep = typename CT::rep; ++ static unsigned CONSTDATA trial_width = ++ detail::width::value; ++public: ++ static unsigned CONSTDATA width = trial_width < 19 ? trial_width : 6u; ++ using precision = std::chrono::duration::value>>; ++ ++private: ++ std::chrono::seconds s_; ++ precision sub_s_; ++ ++public: ++ CONSTCD11 decimal_format_seconds() ++ : s_() ++ , sub_s_() ++ {} ++ ++ CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT ++ : s_(std::chrono::duration_cast(d)) ++ , sub_s_(std::chrono::duration_cast(d - s_)) ++ {} ++ ++ CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;} ++ CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;} ++ CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;} ++ ++ CONSTCD14 precision to_duration() const NOEXCEPT ++ { ++ return s_ + sub_s_; ++ } ++ ++ CONSTCD11 bool in_conventional_range() const NOEXCEPT ++ { ++ return sub_s_ < std::chrono::seconds{1} && s_ < std::chrono::minutes{1}; ++ } ++ ++ template ++ friend ++ std::basic_ostream& ++ operator<<(std::basic_ostream& os, const decimal_format_seconds& x) ++ { ++ return x.print(os, std::chrono::treat_as_floating_point{}); ++ } ++ ++ template ++ std::basic_ostream& ++ print(std::basic_ostream& os, std::true_type) const ++ { ++ date::detail::save_ostream _(os); ++ std::chrono::duration d = s_ + sub_s_; ++ if (d < std::chrono::seconds{10}) ++ os << '0'; ++ os.precision(width+6); ++ os << std::fixed << d.count(); ++ return os; ++ } ++ ++ template ++ std::basic_ostream& ++ print(std::basic_ostream& os, std::false_type) const ++ { ++ date::detail::save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << s_.count(); ++ if (width > 0) ++ { ++#if !ONLY_C_LOCALE ++ os << std::use_facet>(os.getloc()).decimal_point(); ++#else ++ os << '.'; ++#endif ++ date::detail::save_ostream _s(os); ++ os.imbue(std::locale::classic()); ++ os.width(width); ++ os << sub_s_.count(); ++ } ++ return os; ++ } ++}; ++ ++template ++inline ++CONSTCD11 ++typename std::enable_if ++ < ++ std::numeric_limits::is_signed, ++ std::chrono::duration ++ >::type ++abs(std::chrono::duration d) ++{ ++ return d >= d.zero() ? +d : -d; ++} ++ ++template ++inline ++CONSTCD11 ++typename std::enable_if ++ < ++ !std::numeric_limits::is_signed, ++ std::chrono::duration ++ >::type ++abs(std::chrono::duration d) ++{ ++ return d; ++} ++ ++} // namespace detail ++ ++template ++class hh_mm_ss ++{ ++ using dfs = detail::decimal_format_seconds::type>; ++ ++ std::chrono::hours h_; ++ std::chrono::minutes m_; ++ dfs s_; ++ bool neg_; ++ ++public: ++ static unsigned CONSTDATA fractional_width = dfs::width; ++ using precision = typename dfs::precision; ++ ++ CONSTCD11 hh_mm_ss() NOEXCEPT ++ : hh_mm_ss(Duration::zero()) ++ {} ++ ++ CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT ++ : h_(std::chrono::duration_cast(detail::abs(d))) ++ , m_(std::chrono::duration_cast(detail::abs(d)) - h_) ++ , s_(detail::abs(d) - h_ - m_) ++ , neg_(d < Duration::zero()) ++ {} ++ ++ CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} ++ CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} ++ CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();} ++ CONSTCD14 std::chrono::seconds& ++ seconds(detail::undocumented) NOEXCEPT {return s_.seconds();} ++ CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();} ++ CONSTCD11 bool is_negative() const NOEXCEPT {return neg_;} ++ ++ CONSTCD11 explicit operator precision() const NOEXCEPT {return to_duration();} ++ CONSTCD11 precision to_duration() const NOEXCEPT ++ {return (s_.to_duration() + m_ + h_) * (1-2*neg_);} ++ ++ CONSTCD11 bool in_conventional_range() const NOEXCEPT ++ { ++ return !neg_ && h_ < days{1} && m_ < std::chrono::hours{1} && ++ s_.in_conventional_range(); ++ } ++ ++private: ++ ++ template ++ friend ++ std::basic_ostream& ++ operator<<(std::basic_ostream& os, hh_mm_ss const& tod) ++ { ++ if (tod.is_negative()) ++ os << '-'; ++ if (tod.h_ < std::chrono::hours{10}) ++ os << '0'; ++ os << tod.h_.count() << ':'; ++ if (tod.m_ < std::chrono::minutes{10}) ++ os << '0'; ++ os << tod.m_.count() << ':' << tod.s_; ++ return os; ++ } ++ ++ template ++ friend ++ std::basic_ostream& ++ date::to_stream(std::basic_ostream& os, const CharT* fmt, ++ const fields& fds, const std::string* abbrev, ++ const std::chrono::seconds* offset_sec); ++ ++ template ++ friend ++ std::basic_istream& ++ date::from_stream(std::basic_istream& is, const CharT* fmt, ++ fields& fds, ++ std::basic_string* abbrev, std::chrono::minutes* offset); ++}; ++ ++inline ++CONSTCD14 ++bool ++is_am(std::chrono::hours const& h) NOEXCEPT ++{ ++ using std::chrono::hours; ++ return hours{0} <= h && h < hours{12}; ++} ++ ++inline ++CONSTCD14 ++bool ++is_pm(std::chrono::hours const& h) NOEXCEPT ++{ ++ using std::chrono::hours; ++ return hours{12} <= h && h < hours{24}; ++} ++ ++inline ++CONSTCD14 ++std::chrono::hours ++make12(std::chrono::hours h) NOEXCEPT ++{ ++ using std::chrono::hours; ++ if (h < hours{12}) ++ { ++ if (h == hours{0}) ++ h = hours{12}; ++ } ++ else ++ { ++ if (h != hours{12}) ++ h = h - hours{12}; ++ } ++ return h; ++} ++ ++inline ++CONSTCD14 ++std::chrono::hours ++make24(std::chrono::hours h, bool is_pm) NOEXCEPT ++{ ++ using std::chrono::hours; ++ if (is_pm) ++ { ++ if (h != hours{12}) ++ h = h + hours{12}; ++ } ++ else if (h == hours{12}) ++ h = hours{0}; ++ return h; ++} ++ ++template ++using time_of_day = hh_mm_ss; ++ ++template ++CONSTCD11 ++inline ++hh_mm_ss> ++make_time(const std::chrono::duration& d) ++{ ++ return hh_mm_ss>(d); ++} ++ ++template ++inline ++typename std::enable_if ++< ++ !std::is_convertible::value, ++ std::basic_ostream& ++>::type ++operator<<(std::basic_ostream& os, const sys_time& tp) ++{ ++ auto const dp = date::floor(tp); ++ return os << year_month_day(dp) << ' ' << make_time(tp-dp); ++} ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const sys_days& dp) ++{ ++ return os << year_month_day(dp); ++} ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, const local_time& ut) ++{ ++ return (os << sys_time{ut.time_since_epoch()}); ++} ++ ++namespace detail ++{ ++ ++template ++class string_literal; ++ ++template ++inline ++CONSTCD14 ++string_literal::type, ++ N1 + N2 - 1> ++operator+(const string_literal& x, const string_literal& y) NOEXCEPT; ++ ++template ++class string_literal ++{ ++ CharT p_[N]; ++ ++ CONSTCD11 string_literal() NOEXCEPT ++ : p_{} ++ {} ++ ++public: ++ using const_iterator = const CharT*; ++ ++ string_literal(string_literal const&) = default; ++ string_literal& operator=(string_literal const&) = delete; ++ ++ template ::type> ++ CONSTCD11 string_literal(CharT c) NOEXCEPT ++ : p_{c} ++ { ++ } ++ ++ template ::type> ++ CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT ++ : p_{c1, c2} ++ { ++ } ++ ++ template ::type> ++ CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT ++ : p_{c1, c2, c3} ++ { ++ } ++ ++ CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT ++ : p_{} ++ { ++ for (std::size_t i = 0; i < N; ++i) ++ p_[i] = a[i]; ++ } ++ ++ template ::type> ++ CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT ++ : p_{} ++ { ++ for (std::size_t i = 0; i < N; ++i) ++ p_[i] = a[i]; ++ } ++ ++ template ::value>::type> ++ CONSTCD14 string_literal(string_literal const& a) NOEXCEPT ++ : p_{} ++ { ++ for (std::size_t i = 0; i < N; ++i) ++ p_[i] = a[i]; ++ } ++ ++ CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} ++ CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} ++ ++ CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} ++ CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} ++ ++ CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT ++ { ++ return p_[n]; ++ } ++ ++ template ++ friend ++ std::basic_ostream& ++ operator<<(std::basic_ostream& os, const string_literal& s) ++ { ++ return os << s.p_; ++ } ++ ++ template ++ friend ++ CONSTCD14 ++ string_literal::type, ++ N1 + N2 - 1> ++ operator+(const string_literal& x, const string_literal& y) NOEXCEPT; ++}; ++ ++template ++CONSTCD11 ++inline ++string_literal ++operator+(const string_literal& x, const string_literal& y) NOEXCEPT ++{ ++ return string_literal(x[0], y[0]); ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++operator+(const string_literal& x, const string_literal& y) NOEXCEPT ++{ ++ return string_literal(x[0], x[1], y[0]); ++} ++ ++template ++CONSTCD14 ++inline ++string_literal::type, ++ N1 + N2 - 1> ++operator+(const string_literal& x, const string_literal& y) NOEXCEPT ++{ ++ using CT = typename std::conditional::type; ++ ++ string_literal r; ++ std::size_t i = 0; ++ for (; i < N1-1; ++i) ++ r.p_[i] = CT(x.p_[i]); ++ for (std::size_t j = 0; j < N2; ++j, ++i) ++ r.p_[i] = CT(y.p_[j]); ++ ++ return r; ++} ++ ++ ++template ++inline ++std::basic_string ++operator+(std::basic_string x, const string_literal& y) ++{ ++ x.append(y.data(), y.size()); ++ return x; ++} ++ ++#if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ ++ && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) ++ ++template ::value || ++ std::is_same::value || ++ std::is_same::value || ++ std::is_same::value>> ++CONSTCD14 ++inline ++string_literal ++msl(CharT c) NOEXCEPT ++{ ++ return string_literal{c}; ++} ++ ++CONSTCD14 ++inline ++std::size_t ++to_string_len(std::intmax_t i) ++{ ++ std::size_t r = 0; ++ do ++ { ++ i /= 10; ++ ++r; ++ } while (i > 0); ++ return r; ++} ++ ++template ++CONSTCD14 ++inline ++std::enable_if_t ++< ++ N < 10, ++ string_literal ++> ++msl() NOEXCEPT ++{ ++ return msl(char(N % 10 + '0')); ++} ++ ++template ++CONSTCD14 ++inline ++std::enable_if_t ++< ++ 10 <= N, ++ string_literal ++> ++msl() NOEXCEPT ++{ ++ return msl() + msl(char(N % 10 + '0')); ++} ++ ++template ++CONSTCD14 ++inline ++std::enable_if_t ++< ++ std::ratio::type::den != 1, ++ string_literal::type::num) + ++ to_string_len(std::ratio::type::den) + 4> ++> ++msl(std::ratio) NOEXCEPT ++{ ++ using R = typename std::ratio::type; ++ return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + ++ msl() + msl(CharT{']'}); ++} ++ ++template ++CONSTCD14 ++inline ++std::enable_if_t ++< ++ std::ratio::type::den == 1, ++ string_literal::type::num) + 3> ++> ++msl(std::ratio) NOEXCEPT ++{ ++ using R = typename std::ratio::type; ++ return msl(CharT{'['}) + msl() + msl(CharT{']'}); ++} ++ ++ ++#else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) ++ ++inline ++std::string ++to_string(std::uint64_t x) ++{ ++ return std::to_string(x); ++} ++ ++template ++inline ++std::basic_string ++to_string(std::uint64_t x) ++{ ++ auto y = std::to_string(x); ++ return std::basic_string(y.begin(), y.end()); ++} ++ ++template ++inline ++typename std::enable_if ++< ++ std::ratio::type::den != 1, ++ std::basic_string ++>::type ++msl(std::ratio) ++{ ++ using R = typename std::ratio::type; ++ return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + ++ to_string(R::den) + CharT{']'}; ++} ++ ++template ++inline ++typename std::enable_if ++< ++ std::ratio::type::den == 1, ++ std::basic_string ++>::type ++msl(std::ratio) ++{ ++ using R = typename std::ratio::type; ++ return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; ++} ++ ++#endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::atto) NOEXCEPT ++{ ++ return string_literal{'a'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::femto) NOEXCEPT ++{ ++ return string_literal{'f'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::pico) NOEXCEPT ++{ ++ return string_literal{'p'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::nano) NOEXCEPT ++{ ++ return string_literal{'n'}; ++} ++ ++template ++CONSTCD11 ++inline ++typename std::enable_if ++< ++ std::is_same::value, ++ string_literal ++>::type ++msl(std::micro) NOEXCEPT ++{ ++ return string_literal{'\xC2', '\xB5'}; ++} ++ ++template ++CONSTCD11 ++inline ++typename std::enable_if ++< ++ !std::is_same::value, ++ string_literal ++>::type ++msl(std::micro) NOEXCEPT ++{ ++ return string_literal{CharT{static_cast('\xB5')}}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::milli) NOEXCEPT ++{ ++ return string_literal{'m'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::centi) NOEXCEPT ++{ ++ return string_literal{'c'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::deca) NOEXCEPT ++{ ++ return string_literal{'d', 'a'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::deci) NOEXCEPT ++{ ++ return string_literal{'d'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::hecto) NOEXCEPT ++{ ++ return string_literal{'h'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::kilo) NOEXCEPT ++{ ++ return string_literal{'k'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::mega) NOEXCEPT ++{ ++ return string_literal{'M'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::giga) NOEXCEPT ++{ ++ return string_literal{'G'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::tera) NOEXCEPT ++{ ++ return string_literal{'T'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::peta) NOEXCEPT ++{ ++ return string_literal{'P'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++msl(std::exa) NOEXCEPT ++{ ++ return string_literal{'E'}; ++} ++ ++template ++CONSTCD11 ++inline ++auto ++get_units(Period p) ++ -> decltype(msl(p) + string_literal{'s'}) ++{ ++ return msl(p) + string_literal{'s'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++get_units(std::ratio<1>) ++{ ++ return string_literal{'s'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++get_units(std::ratio<3600>) ++{ ++ return string_literal{'h'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++get_units(std::ratio<60>) ++{ ++ return string_literal{'m', 'i', 'n'}; ++} ++ ++template ++CONSTCD11 ++inline ++string_literal ++get_units(std::ratio<86400>) ++{ ++ return string_literal{'d'}; ++} ++ ++template > ++struct make_string; ++ ++template <> ++struct make_string ++{ ++ template ++ static ++ std::string ++ from(Rep n) ++ { ++ return std::to_string(n); ++ } ++}; ++ ++template ++struct make_string ++{ ++ template ++ static ++ std::basic_string ++ from(Rep n) ++ { ++ auto s = std::to_string(n); ++ return std::basic_string(s.begin(), s.end()); ++ } ++}; ++ ++template <> ++struct make_string ++{ ++ template ++ static ++ std::wstring ++ from(Rep n) ++ { ++ return std::to_wstring(n); ++ } ++}; ++ ++template ++struct make_string ++{ ++ template ++ static ++ std::basic_string ++ from(Rep n) ++ { ++ auto s = std::to_wstring(n); ++ return std::basic_string(s.begin(), s.end()); ++ } ++}; ++ ++} // namespace detail ++ ++// to_stream ++ ++CONSTDATA year nanyear{-32768}; ++ ++template ++struct fields ++{ ++ year_month_day ymd{nanyear/0/0}; ++ weekday wd{8u}; ++ hh_mm_ss tod{}; ++ bool has_tod = false; ++ ++#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ <= 409) ++ fields() : ymd{nanyear/0/0}, wd{8u}, tod{}, has_tod{false} {} ++#else ++ fields() = default; ++#endif ++ ++ fields(year_month_day ymd_) : ymd(ymd_) {} ++ fields(weekday wd_) : wd(wd_) {} ++ fields(hh_mm_ss tod_) : tod(tod_), has_tod(true) {} ++ ++ fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {} ++ fields(year_month_day ymd_, hh_mm_ss tod_) : ymd(ymd_), tod(tod_), ++ has_tod(true) {} ++ ++ fields(weekday wd_, hh_mm_ss tod_) : wd(wd_), tod(tod_), has_tod(true) {} ++ ++ fields(year_month_day ymd_, weekday wd_, hh_mm_ss tod_) ++ : ymd(ymd_) ++ , wd(wd_) ++ , tod(tod_) ++ , has_tod(true) ++ {} ++}; ++ ++namespace detail ++{ ++ ++template ++unsigned ++extract_weekday(std::basic_ostream& os, const fields& fds) ++{ ++ if (!fds.ymd.ok() && !fds.wd.ok()) ++ { ++ // fds does not contain a valid weekday ++ os.setstate(std::ios::failbit); ++ return 8; ++ } ++ weekday wd; ++ if (fds.ymd.ok()) ++ { ++ wd = weekday{sys_days(fds.ymd)}; ++ if (fds.wd.ok() && wd != fds.wd) ++ { ++ // fds.ymd and fds.wd are inconsistent ++ os.setstate(std::ios::failbit); ++ return 8; ++ } ++ } ++ else ++ wd = fds.wd; ++ return static_cast((wd - Sunday).count()); ++} ++ ++template ++unsigned ++extract_month(std::basic_ostream& os, const fields& fds) ++{ ++ if (!fds.ymd.month().ok()) ++ { ++ // fds does not contain a valid month ++ os.setstate(std::ios::failbit); ++ return 0; ++ } ++ return static_cast(fds.ymd.month()); ++} ++ ++} // namespace detail ++ ++#if ONLY_C_LOCALE ++ ++namespace detail ++{ ++ ++inline ++std::pair ++weekday_names() ++{ ++ static const std::string nm[] = ++ { ++ "Sunday", ++ "Monday", ++ "Tuesday", ++ "Wednesday", ++ "Thursday", ++ "Friday", ++ "Saturday", ++ "Sun", ++ "Mon", ++ "Tue", ++ "Wed", ++ "Thu", ++ "Fri", ++ "Sat" ++ }; ++ return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ++} ++ ++inline ++std::pair ++month_names() ++{ ++ static const std::string nm[] = ++ { ++ "January", ++ "February", ++ "March", ++ "April", ++ "May", ++ "June", ++ "July", ++ "August", ++ "September", ++ "October", ++ "November", ++ "December", ++ "Jan", ++ "Feb", ++ "Mar", ++ "Apr", ++ "May", ++ "Jun", ++ "Jul", ++ "Aug", ++ "Sep", ++ "Oct", ++ "Nov", ++ "Dec" ++ }; ++ return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ++} ++ ++inline ++std::pair ++ampm_names() ++{ ++ static const std::string nm[] = ++ { ++ "AM", ++ "PM" ++ }; ++ return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ++} ++ ++template ++FwdIter ++scan_keyword(std::basic_istream& is, FwdIter kb, FwdIter ke) ++{ ++ size_t nkw = static_cast(std::distance(kb, ke)); ++ const unsigned char doesnt_match = '\0'; ++ const unsigned char might_match = '\1'; ++ const unsigned char does_match = '\2'; ++ unsigned char statbuf[100]; ++ unsigned char* status = statbuf; ++ std::unique_ptr stat_hold(0, free); ++ if (nkw > sizeof(statbuf)) ++ { ++ status = (unsigned char*)std::malloc(nkw); ++ if (status == nullptr) ++ throw std::bad_alloc(); ++ stat_hold.reset(status); ++ } ++ size_t n_might_match = nkw; // At this point, any keyword might match ++ size_t n_does_match = 0; // but none of them definitely do ++ // Initialize all statuses to might_match, except for "" keywords are does_match ++ unsigned char* st = status; ++ for (auto ky = kb; ky != ke; ++ky, ++st) ++ { ++ if (!ky->empty()) ++ *st = might_match; ++ else ++ { ++ *st = does_match; ++ --n_might_match; ++ ++n_does_match; ++ } ++ } ++ // While there might be a match, test keywords against the next CharT ++ for (size_t indx = 0; is && n_might_match > 0; ++indx) ++ { ++ // Peek at the next CharT but don't consume it ++ auto ic = is.peek(); ++ if (ic == EOF) ++ { ++ is.setstate(std::ios::eofbit); ++ break; ++ } ++ auto c = static_cast(toupper(static_cast(ic))); ++ bool consume = false; ++ // For each keyword which might match, see if the indx character is c ++ // If a match if found, consume c ++ // If a match is found, and that is the last character in the keyword, ++ // then that keyword matches. ++ // If the keyword doesn't match this character, then change the keyword ++ // to doesn't match ++ st = status; ++ for (auto ky = kb; ky != ke; ++ky, ++st) ++ { ++ if (*st == might_match) ++ { ++ if (c == static_cast(toupper(static_cast((*ky)[indx])))) ++ { ++ consume = true; ++ if (ky->size() == indx+1) ++ { ++ *st = does_match; ++ --n_might_match; ++ ++n_does_match; ++ } ++ } ++ else ++ { ++ *st = doesnt_match; ++ --n_might_match; ++ } ++ } ++ } ++ // consume if we matched a character ++ if (consume) ++ { ++ (void)is.get(); ++ // If we consumed a character and there might be a matched keyword that ++ // was marked matched on a previous iteration, then such keywords ++ // are now marked as not matching. ++ if (n_might_match + n_does_match > 1) ++ { ++ st = status; ++ for (auto ky = kb; ky != ke; ++ky, ++st) ++ { ++ if (*st == does_match && ky->size() != indx+1) ++ { ++ *st = doesnt_match; ++ --n_does_match; ++ } ++ } ++ } ++ } ++ } ++ // We've exited the loop because we hit eof and/or we have no more "might matches". ++ // Return the first matching result ++ for (st = status; kb != ke; ++kb, ++st) ++ if (*st == does_match) ++ break; ++ if (kb == ke) ++ is.setstate(std::ios::failbit); ++ return kb; ++} ++ ++} // namespace detail ++ ++#endif // ONLY_C_LOCALE ++ ++template ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const fields& fds, const std::string* abbrev, ++ const std::chrono::seconds* offset_sec) ++{ ++#if ONLY_C_LOCALE ++ using detail::weekday_names; ++ using detail::month_names; ++ using detail::ampm_names; ++#endif ++ using detail::save_ostream; ++ using detail::get_units; ++ using detail::extract_weekday; ++ using detail::extract_month; ++ using std::ios; ++ using std::chrono::duration_cast; ++ using std::chrono::seconds; ++ using std::chrono::minutes; ++ using std::chrono::hours; ++ date::detail::save_ostream ss(os); ++ os.fill(' '); ++ os.flags(std::ios::skipws | std::ios::dec); ++ os.width(0); ++ tm tm{}; ++ bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero(); ++#if !ONLY_C_LOCALE ++ auto& facet = std::use_facet>(os.getloc()); ++#endif ++ const CharT* command = nullptr; ++ CharT modified = CharT{}; ++ for (; *fmt; ++fmt) ++ { ++ switch (*fmt) ++ { ++ case 'a': ++ case 'A': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ tm.tm_wday = static_cast(extract_weekday(os, fds)); ++ if (os.fail()) ++ return os; ++#if !ONLY_C_LOCALE ++ const CharT f[] = {'%', *fmt}; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++#else // ONLY_C_LOCALE ++ os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')]; ++#endif // ONLY_C_LOCALE ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'b': ++ case 'B': ++ case 'h': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ tm.tm_mon = static_cast(extract_month(os, fds)) - 1; ++#if !ONLY_C_LOCALE ++ const CharT f[] = {'%', *fmt}; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++#else // ONLY_C_LOCALE ++ os << month_names().first[tm.tm_mon+12*(*fmt != 'B')]; ++#endif // ONLY_C_LOCALE ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'c': ++ case 'x': ++ if (command) ++ { ++ if (modified == CharT{'O'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.ok()) ++ os.setstate(std::ios::failbit); ++ if (*fmt == 'c' && !fds.has_tod) ++ os.setstate(std::ios::failbit); ++#if !ONLY_C_LOCALE ++ tm = std::tm{}; ++ auto const& ymd = fds.ymd; ++ auto ld = local_days(ymd); ++ if (*fmt == 'c') ++ { ++ tm.tm_sec = static_cast(fds.tod.seconds().count()); ++ tm.tm_min = static_cast(fds.tod.minutes().count()); ++ tm.tm_hour = static_cast(fds.tod.hours().count()); ++ } ++ tm.tm_mday = static_cast(static_cast(ymd.day())); ++ tm.tm_mon = static_cast(extract_month(os, fds) - 1); ++ tm.tm_year = static_cast(ymd.year()) - 1900; ++ tm.tm_wday = static_cast(extract_weekday(os, fds)); ++ if (os.fail()) ++ return os; ++ tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ++ CharT f[3] = {'%'}; ++ auto fe = std::begin(f) + 1; ++ if (modified == CharT{'E'}) ++ *fe++ = modified; ++ *fe++ = *fmt; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), fe); ++#else // ONLY_C_LOCALE ++ if (*fmt == 'c') ++ { ++ auto wd = static_cast(extract_weekday(os, fds)); ++ os << weekday_names().first[static_cast(wd)+7] ++ << ' '; ++ os << month_names().first[extract_month(os, fds)-1+12] << ' '; ++ auto d = static_cast(static_cast(fds.ymd.day())); ++ if (d < 10) ++ os << ' '; ++ os << d << ' ' ++ << make_time(duration_cast(fds.tod.to_duration())) ++ << ' ' << fds.ymd.year(); ++ ++ } ++ else // *fmt == 'x' ++ { ++ auto const& ymd = fds.ymd; ++ save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << static_cast(ymd.month()) << CharT{'/'}; ++ os.width(2); ++ os << static_cast(ymd.day()) << CharT{'/'}; ++ os.width(2); ++ os << static_cast(ymd.year()) % 100; ++ } ++#endif // ONLY_C_LOCALE ++ } ++ command = nullptr; ++ modified = CharT{}; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'C': ++ if (command) ++ { ++ if (modified == CharT{'O'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.year().ok()) ++ os.setstate(std::ios::failbit); ++ auto y = static_cast(fds.ymd.year()); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ if (y >= 0) ++ { ++ os.width(2); ++ os << y/100; ++ } ++ else ++ { ++ os << CharT{'-'}; ++ os.width(2); ++ os << -(y-99)/100; ++ } ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'E'}) ++ { ++ tm.tm_year = y - 1900; ++ CharT f[3] = {'%', 'E', 'C'}; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ command = nullptr; ++ modified = CharT{}; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'd': ++ case 'e': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.day().ok()) ++ os.setstate(std::ios::failbit); ++ auto d = static_cast(static_cast(fds.ymd.day())); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ save_ostream _(os); ++ if (*fmt == CharT{'d'}) ++ os.fill('0'); ++ else ++ os.fill(' '); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << d; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ tm.tm_mday = d; ++ CharT f[3] = {'%', 'O', *fmt}; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ command = nullptr; ++ modified = CharT{}; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'D': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto const& ymd = fds.ymd; ++ save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << static_cast(ymd.month()) << CharT{'/'}; ++ os.width(2); ++ os << static_cast(ymd.day()) << CharT{'/'}; ++ os.width(2); ++ os << static_cast(ymd.year()) % 100; ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'F': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto const& ymd = fds.ymd; ++ save_ostream _(os); ++ os.imbue(std::locale::classic()); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(4); ++ os << static_cast(ymd.year()) << CharT{'-'}; ++ os.width(2); ++ os << static_cast(ymd.month()) << CharT{'-'}; ++ os.width(2); ++ os << static_cast(ymd.day()); ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'g': ++ case 'G': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto ld = local_days(fds.ymd); ++ auto y = year_month_day{ld + days{3}}.year(); ++ auto start = local_days((y-years{1})/December/Thursday[last]) + ++ (Monday-Thursday); ++ if (ld < start) ++ --y; ++ if (*fmt == CharT{'G'}) ++ os << y; ++ else ++ { ++ save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(2); ++ os << std::abs(static_cast(y)) % 100; ++ } ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'H': ++ case 'I': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ if (insert_negative) ++ { ++ os << '-'; ++ insert_negative = false; ++ } ++ auto hms = fds.tod; ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ auto h = *fmt == CharT{'I'} ? date::make12(hms.hours()) : hms.hours(); ++ if (h < hours{10}) ++ os << CharT{'0'}; ++ os << h.count(); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_hour = static_cast(hms.hours().count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'j': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (fds.ymd.ok() || fds.has_tod) ++ { ++ days doy; ++ if (fds.ymd.ok()) ++ { ++ auto ld = local_days(fds.ymd); ++ auto y = fds.ymd.year(); ++ doy = ld - local_days(y/January/1) + days{1}; ++ } ++ else ++ { ++ doy = duration_cast(fds.tod.to_duration()); ++ } ++ save_ostream _(os); ++ os.fill('0'); ++ os.flags(std::ios::dec | std::ios::right); ++ os.width(3); ++ os << doy.count(); ++ } ++ else ++ { ++ os.setstate(std::ios::failbit); ++ } ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'm': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.month().ok()) ++ os.setstate(std::ios::failbit); ++ auto m = static_cast(fds.ymd.month()); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ if (m < 10) ++ os << CharT{'0'}; ++ os << m; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_mon = static_cast(m-1); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'M': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ if (insert_negative) ++ { ++ os << '-'; ++ insert_negative = false; ++ } ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ if (fds.tod.minutes() < minutes{10}) ++ os << CharT{'0'}; ++ os << fds.tod.minutes().count(); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_min = static_cast(fds.tod.minutes().count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'n': ++ if (command) ++ { ++ if (modified == CharT{}) ++ os << CharT{'\n'}; ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'p': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++#if !ONLY_C_LOCALE ++ const CharT f[] = {'%', *fmt}; ++ tm.tm_hour = static_cast(fds.tod.hours().count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++#else ++ if (date::is_am(fds.tod.hours())) ++ os << ampm_names().first[0]; ++ else ++ os << ampm_names().first[1]; ++#endif ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'Q': ++ case 'q': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ auto d = fds.tod.to_duration(); ++ if (*fmt == 'q') ++ os << get_units(typename decltype(d)::period::type{}); ++ else ++ os << d.count(); ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'r': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++#if !ONLY_C_LOCALE ++ const CharT f[] = {'%', *fmt}; ++ tm.tm_hour = static_cast(fds.tod.hours().count()); ++ tm.tm_min = static_cast(fds.tod.minutes().count()); ++ tm.tm_sec = static_cast(fds.tod.seconds().count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++#else ++ hh_mm_ss tod(duration_cast(fds.tod.to_duration())); ++ save_ostream _(os); ++ os.fill('0'); ++ os.width(2); ++ os << date::make12(tod.hours()).count() << CharT{':'}; ++ os.width(2); ++ os << tod.minutes().count() << CharT{':'}; ++ os.width(2); ++ os << tod.seconds().count() << CharT{' '}; ++ if (date::is_am(tod.hours())) ++ os << ampm_names().first[0]; ++ else ++ os << ampm_names().first[1]; ++#endif ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'R': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ if (fds.tod.hours() < hours{10}) ++ os << CharT{'0'}; ++ os << fds.tod.hours().count() << CharT{':'}; ++ if (fds.tod.minutes() < minutes{10}) ++ os << CharT{'0'}; ++ os << fds.tod.minutes().count(); ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'S': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ if (insert_negative) ++ { ++ os << '-'; ++ insert_negative = false; ++ } ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ os << fds.tod.s_; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_sec = static_cast(fds.tod.s_.seconds().count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 't': ++ if (command) ++ { ++ if (modified == CharT{}) ++ os << CharT{'\t'}; ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'T': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++ os << fds.tod; ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'u': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ auto wd = extract_weekday(os, fds); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ os << (wd != 0 ? wd : 7u); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_wday = static_cast(wd); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'U': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ auto const& ymd = fds.ymd; ++ if (!ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto ld = local_days(ymd); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ auto st = local_days(Sunday[1]/January/ymd.year()); ++ if (ld < st) ++ os << CharT{'0'} << CharT{'0'}; ++ else ++ { ++ auto wn = duration_cast(ld - st).count() + 1; ++ if (wn < 10) ++ os << CharT{'0'}; ++ os << wn; ++ } ++ } ++ #if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_year = static_cast(ymd.year()) - 1900; ++ tm.tm_wday = static_cast(extract_weekday(os, fds)); ++ if (os.fail()) ++ return os; ++ tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'V': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto ld = local_days(fds.ymd); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ auto y = year_month_day{ld + days{3}}.year(); ++ auto st = local_days((y-years{1})/12/Thursday[last]) + ++ (Monday-Thursday); ++ if (ld < st) ++ { ++ --y; ++ st = local_days((y - years{1})/12/Thursday[last]) + ++ (Monday-Thursday); ++ } ++ auto wn = duration_cast(ld - st).count() + 1; ++ if (wn < 10) ++ os << CharT{'0'}; ++ os << wn; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ auto const& ymd = fds.ymd; ++ tm.tm_year = static_cast(ymd.year()) - 1900; ++ tm.tm_wday = static_cast(extract_weekday(os, fds)); ++ if (os.fail()) ++ return os; ++ tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'w': ++ if (command) ++ { ++ auto wd = extract_weekday(os, fds); ++ if (os.fail()) ++ return os; ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ os << wd; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_wday = static_cast(wd); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'W': ++ if (command) ++ { ++ if (modified == CharT{'E'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ auto const& ymd = fds.ymd; ++ if (!ymd.ok()) ++ os.setstate(std::ios::failbit); ++ auto ld = local_days(ymd); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ auto st = local_days(Monday[1]/January/ymd.year()); ++ if (ld < st) ++ os << CharT{'0'} << CharT{'0'}; ++ else ++ { ++ auto wn = duration_cast(ld - st).count() + 1; ++ if (wn < 10) ++ os << CharT{'0'}; ++ os << wn; ++ } ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_year = static_cast(ymd.year()) - 1900; ++ tm.tm_wday = static_cast(extract_weekday(os, fds)); ++ if (os.fail()) ++ return os; ++ tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'X': ++ if (command) ++ { ++ if (modified == CharT{'O'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.has_tod) ++ os.setstate(std::ios::failbit); ++#if !ONLY_C_LOCALE ++ tm = std::tm{}; ++ tm.tm_sec = static_cast(fds.tod.seconds().count()); ++ tm.tm_min = static_cast(fds.tod.minutes().count()); ++ tm.tm_hour = static_cast(fds.tod.hours().count()); ++ CharT f[3] = {'%'}; ++ auto fe = std::begin(f) + 1; ++ if (modified == CharT{'E'}) ++ *fe++ = modified; ++ *fe++ = *fmt; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), fe); ++#else ++ os << fds.tod; ++#endif ++ } ++ command = nullptr; ++ modified = CharT{}; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'y': ++ if (command) ++ { ++ if (!fds.ymd.year().ok()) ++ os.setstate(std::ios::failbit); ++ auto y = static_cast(fds.ymd.year()); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++ { ++#endif ++ y = std::abs(y) % 100; ++ if (y < 10) ++ os << CharT{'0'}; ++ os << y; ++#if !ONLY_C_LOCALE ++ } ++ else ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_year = y - 1900; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'Y': ++ if (command) ++ { ++ if (modified == CharT{'O'}) ++ os << CharT{'%'} << modified << *fmt; ++ else ++ { ++ if (!fds.ymd.year().ok()) ++ os.setstate(std::ios::failbit); ++ auto y = fds.ymd.year(); ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ save_ostream _(os); ++ os.imbue(std::locale::classic()); ++ os << y; ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'E'}) ++ { ++ const CharT f[] = {'%', modified, *fmt}; ++ tm.tm_year = static_cast(y) - 1900; ++ facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ++ } ++#endif ++ } ++ modified = CharT{}; ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'z': ++ if (command) ++ { ++ if (offset_sec == nullptr) ++ { ++ // Can not format %z with unknown offset ++ os.setstate(ios::failbit); ++ return os; ++ } ++ auto m = duration_cast(*offset_sec); ++ auto neg = m < minutes{0}; ++ m = date::abs(m); ++ auto h = duration_cast(m); ++ m -= h; ++ if (neg) ++ os << CharT{'-'}; ++ else ++ os << CharT{'+'}; ++ if (h < hours{10}) ++ os << CharT{'0'}; ++ os << h.count(); ++ if (modified != CharT{}) ++ os << CharT{':'}; ++ if (m < minutes{10}) ++ os << CharT{'0'}; ++ os << m.count(); ++ command = nullptr; ++ modified = CharT{}; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'Z': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ if (abbrev == nullptr) ++ { ++ // Can not format %Z with unknown time_zone ++ os.setstate(ios::failbit); ++ return os; ++ } ++ for (auto c : *abbrev) ++ os << CharT(c); ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ modified = CharT{}; ++ } ++ command = nullptr; ++ } ++ else ++ os << *fmt; ++ break; ++ case 'E': ++ case 'O': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ modified = *fmt; ++ } ++ else ++ { ++ os << CharT{'%'} << modified << *fmt; ++ command = nullptr; ++ modified = CharT{}; ++ } ++ } ++ else ++ os << *fmt; ++ break; ++ case '%': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ os << CharT{'%'}; ++ command = nullptr; ++ } ++ else ++ { ++ os << CharT{'%'} << modified << CharT{'%'}; ++ command = nullptr; ++ modified = CharT{}; ++ } ++ } ++ else ++ command = fmt; ++ break; ++ default: ++ if (command) ++ { ++ os << CharT{'%'}; ++ command = nullptr; ++ } ++ if (modified != CharT{}) ++ { ++ os << modified; ++ modified = CharT{}; ++ } ++ os << *fmt; ++ break; ++ } ++ } ++ if (command) ++ os << CharT{'%'}; ++ if (modified != CharT{}) ++ os << modified; ++ return os; ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const year& y) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{y/0/0}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const month& m) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{m/0/nanyear}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const day& d) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{d/0/nanyear}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const weekday& wd) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{wd}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const year_month& ym) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{ym/0}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, const month_day& md) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{md/nanyear}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const year_month_day& ymd) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{ymd}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++inline ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const std::chrono::duration& d) ++{ ++ using Duration = std::chrono::duration; ++ using CT = typename std::common_type::type; ++ fields fds{hh_mm_ss{d}}; ++ return to_stream(os, fmt, fds); ++} ++ ++template ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const local_time& tp, const std::string* abbrev = nullptr, ++ const std::chrono::seconds* offset_sec = nullptr) ++{ ++ using CT = typename std::common_type::type; ++ auto ld = std::chrono::time_point_cast(tp); ++ fields fds; ++ if (ld <= tp) ++ fds = fields{year_month_day{ld}, hh_mm_ss{tp-local_seconds{ld}}}; ++ else ++ fds = fields{year_month_day{ld - days{1}}, ++ hh_mm_ss{days{1} - (local_seconds{ld} - tp)}}; ++ return to_stream(os, fmt, fds, abbrev, offset_sec); ++} ++ ++template ++std::basic_ostream& ++to_stream(std::basic_ostream& os, const CharT* fmt, ++ const sys_time& tp) ++{ ++ using std::chrono::seconds; ++ using CT = typename std::common_type::type; ++ const std::string abbrev("UTC"); ++ CONSTDATA seconds offset{0}; ++ auto sd = std::chrono::time_point_cast(tp); ++ fields fds; ++ if (sd <= tp) ++ fds = fields{year_month_day{sd}, hh_mm_ss{tp-sys_seconds{sd}}}; ++ else ++ fds = fields{year_month_day{sd - days{1}}, ++ hh_mm_ss{days{1} - (sys_seconds{sd} - tp)}}; ++ return to_stream(os, fmt, fds, &abbrev, &offset); ++} ++ ++// format ++ ++template ++auto ++format(const std::locale& loc, const CharT* fmt, const Streamable& tp) ++ -> decltype(to_stream(std::declval&>(), fmt, tp), ++ std::basic_string{}) ++{ ++ std::basic_ostringstream os; ++ os.exceptions(std::ios::failbit | std::ios::badbit); ++ os.imbue(loc); ++ to_stream(os, fmt, tp); ++ return os.str(); ++} ++ ++template ++auto ++format(const CharT* fmt, const Streamable& tp) ++ -> decltype(to_stream(std::declval&>(), fmt, tp), ++ std::basic_string{}) ++{ ++ std::basic_ostringstream os; ++ os.exceptions(std::ios::failbit | std::ios::badbit); ++ to_stream(os, fmt, tp); ++ return os.str(); ++} ++ ++template ++auto ++format(const std::locale& loc, const std::basic_string& fmt, ++ const Streamable& tp) ++ -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), ++ std::basic_string{}) ++{ ++ std::basic_ostringstream os; ++ os.exceptions(std::ios::failbit | std::ios::badbit); ++ os.imbue(loc); ++ to_stream(os, fmt.c_str(), tp); ++ return os.str(); ++} ++ ++template ++auto ++format(const std::basic_string& fmt, const Streamable& tp) ++ -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), ++ std::basic_string{}) ++{ ++ std::basic_ostringstream os; ++ os.exceptions(std::ios::failbit | std::ios::badbit); ++ to_stream(os, fmt.c_str(), tp); ++ return os.str(); ++} ++ ++// parse ++ ++namespace detail ++{ ++ ++template ++bool ++read_char(std::basic_istream& is, CharT fmt, std::ios::iostate& err) ++{ ++ auto ic = is.get(); ++ if (Traits::eq_int_type(ic, Traits::eof()) || ++ !Traits::eq(Traits::to_char_type(ic), fmt)) ++ { ++ err |= std::ios::failbit; ++ is.setstate(std::ios::failbit); ++ return false; ++ } ++ return true; ++} ++ ++template ++unsigned ++read_unsigned(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ++{ ++ unsigned x = 0; ++ unsigned count = 0; ++ while (true) ++ { ++ auto ic = is.peek(); ++ if (Traits::eq_int_type(ic, Traits::eof())) ++ break; ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if (!('0' <= c && c <= '9')) ++ break; ++ (void)is.get(); ++ ++count; ++ x = 10*x + static_cast(c - '0'); ++ if (count == M) ++ break; ++ } ++ if (count < m) ++ is.setstate(std::ios::failbit); ++ return x; ++} ++ ++template ++int ++read_signed(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ++{ ++ auto ic = is.peek(); ++ if (!Traits::eq_int_type(ic, Traits::eof())) ++ { ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if (('0' <= c && c <= '9') || c == '-' || c == '+') ++ { ++ if (c == '-' || c == '+') ++ (void)is.get(); ++ auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); ++ if (!is.fail()) ++ { ++ if (c == '-') ++ x = -x; ++ return x; ++ } ++ } ++ } ++ if (m > 0) ++ is.setstate(std::ios::failbit); ++ return 0; ++} ++ ++template ++long double ++read_long_double(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ++{ ++ unsigned count = 0; ++ unsigned fcount = 0; ++ unsigned long long i = 0; ++ unsigned long long f = 0; ++ bool parsing_fraction = false; ++#if ONLY_C_LOCALE ++ typename Traits::int_type decimal_point = '.'; ++#else ++ auto decimal_point = Traits::to_int_type( ++ std::use_facet>(is.getloc()).decimal_point()); ++#endif ++ while (true) ++ { ++ auto ic = is.peek(); ++ if (Traits::eq_int_type(ic, Traits::eof())) ++ break; ++ if (Traits::eq_int_type(ic, decimal_point)) ++ { ++ decimal_point = Traits::eof(); ++ parsing_fraction = true; ++ } ++ else ++ { ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if (!('0' <= c && c <= '9')) ++ break; ++ if (!parsing_fraction) ++ { ++ i = 10*i + static_cast(c - '0'); ++ } ++ else ++ { ++ f = 10*f + static_cast(c - '0'); ++ ++fcount; ++ } ++ } ++ (void)is.get(); ++ if (++count == M) ++ break; ++ } ++ if (count < m) ++ { ++ is.setstate(std::ios::failbit); ++ return 0; ++ } ++ return static_cast(i) + static_cast(f)/std::pow(10.L, fcount); ++} ++ ++struct rs ++{ ++ int& i; ++ unsigned m; ++ unsigned M; ++}; ++ ++struct ru ++{ ++ int& i; ++ unsigned m; ++ unsigned M; ++}; ++ ++struct rld ++{ ++ long double& i; ++ unsigned m; ++ unsigned M; ++}; ++ ++template ++void ++read(std::basic_istream&) ++{ ++} ++ ++template ++void ++read(std::basic_istream& is, CharT a0, Args&& ...args); ++ ++template ++void ++read(std::basic_istream& is, rs a0, Args&& ...args); ++ ++template ++void ++read(std::basic_istream& is, ru a0, Args&& ...args); ++ ++template ++void ++read(std::basic_istream& is, int a0, Args&& ...args); ++ ++template ++void ++read(std::basic_istream& is, rld a0, Args&& ...args); ++ ++template ++void ++read(std::basic_istream& is, CharT a0, Args&& ...args) ++{ ++ // No-op if a0 == CharT{} ++ if (a0 != CharT{}) ++ { ++ auto ic = is.peek(); ++ if (Traits::eq_int_type(ic, Traits::eof())) ++ { ++ is.setstate(std::ios::failbit | std::ios::eofbit); ++ return; ++ } ++ if (!Traits::eq(Traits::to_char_type(ic), a0)) ++ { ++ is.setstate(std::ios::failbit); ++ return; ++ } ++ (void)is.get(); ++ } ++ read(is, std::forward(args)...); ++} ++ ++template ++void ++read(std::basic_istream& is, rs a0, Args&& ...args) ++{ ++ auto x = read_signed(is, a0.m, a0.M); ++ if (is.fail()) ++ return; ++ a0.i = x; ++ read(is, std::forward(args)...); ++} ++ ++template ++void ++read(std::basic_istream& is, ru a0, Args&& ...args) ++{ ++ auto x = read_unsigned(is, a0.m, a0.M); ++ if (is.fail()) ++ return; ++ a0.i = static_cast(x); ++ read(is, std::forward(args)...); ++} ++ ++template ++void ++read(std::basic_istream& is, int a0, Args&& ...args) ++{ ++ if (a0 != -1) ++ { ++ auto u = static_cast(a0); ++ CharT buf[std::numeric_limits::digits10+2u] = {}; ++ auto e = buf; ++ do ++ { ++ *e++ = static_cast(CharT(u % 10) + CharT{'0'}); ++ u /= 10; ++ } while (u > 0); ++ std::reverse(buf, e); ++ for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) ++ read(is, *p); ++ } ++ if (is.rdstate() == std::ios::goodbit) ++ read(is, std::forward(args)...); ++} ++ ++template ++void ++read(std::basic_istream& is, rld a0, Args&& ...args) ++{ ++ auto x = read_long_double(is, a0.m, a0.M); ++ if (is.fail()) ++ return; ++ a0.i = x; ++ read(is, std::forward(args)...); ++} ++ ++template ++inline ++void ++checked_set(T& value, T from, T not_a_value, std::basic_ios& is) ++{ ++ if (!is.fail()) ++ { ++ if (value == not_a_value) ++ value = std::move(from); ++ else if (value != from) ++ is.setstate(std::ios::failbit); ++ } ++} ++ ++} // namespace detail; ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ fields& fds, std::basic_string* abbrev, ++ std::chrono::minutes* offset) ++{ ++ using std::numeric_limits; ++ using std::ios; ++ using std::chrono::duration; ++ using std::chrono::duration_cast; ++ using std::chrono::seconds; ++ using std::chrono::minutes; ++ using std::chrono::hours; ++ using detail::round_i; ++ typename std::basic_istream::sentry ok{is, true}; ++ if (ok) ++ { ++ date::detail::save_istream ss(is); ++ is.fill(' '); ++ is.flags(std::ios::skipws | std::ios::dec); ++ is.width(0); ++#if !ONLY_C_LOCALE ++ auto& f = std::use_facet>(is.getloc()); ++ std::tm tm{}; ++#endif ++ const CharT* command = nullptr; ++ auto modified = CharT{}; ++ auto width = -1; ++ ++ CONSTDATA int not_a_year = numeric_limits::min(); ++ CONSTDATA int not_a_2digit_year = 100; ++ CONSTDATA int not_a_century = not_a_year / 100; ++ CONSTDATA int not_a_month = 0; ++ CONSTDATA int not_a_day = 0; ++ CONSTDATA int not_a_hour = numeric_limits::min(); ++ CONSTDATA int not_a_hour_12_value = 0; ++ CONSTDATA int not_a_minute = not_a_hour; ++ CONSTDATA Duration not_a_second = Duration::min(); ++ CONSTDATA int not_a_doy = -1; ++ CONSTDATA int not_a_weekday = 8; ++ CONSTDATA int not_a_week_num = 100; ++ CONSTDATA int not_a_ampm = -1; ++ CONSTDATA minutes not_a_offset = minutes::min(); ++ ++ int Y = not_a_year; // c, F, Y * ++ int y = not_a_2digit_year; // D, x, y * ++ int g = not_a_2digit_year; // g * ++ int G = not_a_year; // G * ++ int C = not_a_century; // C * ++ int m = not_a_month; // b, B, h, m, c, D, F, x * ++ int d = not_a_day; // c, d, D, e, F, x * ++ int j = not_a_doy; // j * ++ int wd = not_a_weekday; // a, A, u, w * ++ int H = not_a_hour; // c, H, R, T, X * ++ int I = not_a_hour_12_value; // I, r * ++ int p = not_a_ampm; // p, r * ++ int M = not_a_minute; // c, M, r, R, T, X * ++ Duration s = not_a_second; // c, r, S, T, X * ++ int U = not_a_week_num; // U * ++ int V = not_a_week_num; // V * ++ int W = not_a_week_num; // W * ++ std::basic_string temp_abbrev; // Z * ++ minutes temp_offset = not_a_offset; // z * ++ ++ using detail::read; ++ using detail::rs; ++ using detail::ru; ++ using detail::rld; ++ using detail::checked_set; ++ for (; *fmt != CharT{} && !is.fail(); ++fmt) ++ { ++ switch (*fmt) ++ { ++ case 'a': ++ case 'A': ++ case 'u': ++ case 'w': // wd: a, A, u, w ++ if (command) ++ { ++ int trial_wd = not_a_weekday; ++ if (*fmt == 'a' || *fmt == 'A') ++ { ++ if (modified == CharT{}) ++ { ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ is.setstate(err); ++ if (!is.fail()) ++ trial_wd = tm.tm_wday; ++#else ++ auto nm = detail::weekday_names(); ++ auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ if (!is.fail()) ++ trial_wd = i % 7; ++#endif ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ } ++ else // *fmt == 'u' || *fmt == 'w' ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ read(is, ru{trial_wd, 1, width == -1 ? ++ 1u : static_cast(width)}); ++ if (!is.fail()) ++ { ++ if (*fmt == 'u') ++ { ++ if (!(1 <= trial_wd && trial_wd <= 7)) ++ { ++ trial_wd = not_a_weekday; ++ is.setstate(ios::failbit); ++ } ++ else if (trial_wd == 7) ++ trial_wd = 0; ++ } ++ else // *fmt == 'w' ++ { ++ if (!(0 <= trial_wd && trial_wd <= 6)) ++ { ++ trial_wd = not_a_weekday; ++ is.setstate(ios::failbit); ++ } ++ } ++ } ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ is.setstate(err); ++ if (!is.fail()) ++ trial_wd = tm.tm_wday; ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ } ++ if (trial_wd != not_a_weekday) ++ checked_set(wd, trial_wd, not_a_weekday, is); ++ } ++ else // !command ++ read(is, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ break; ++ case 'b': ++ case 'B': ++ case 'h': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int ttm = not_a_month; ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ ttm = tm.tm_mon + 1; ++ is.setstate(err); ++#else ++ auto nm = detail::month_names(); ++ auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ if (!is.fail()) ++ ttm = i % 12 + 1; ++#endif ++ checked_set(m, ttm, not_a_month, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'c': ++ if (command) ++ { ++ if (modified != CharT{'O'}) ++ { ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ { ++ checked_set(Y, tm.tm_year + 1900, not_a_year, is); ++ checked_set(m, tm.tm_mon + 1, not_a_month, is); ++ checked_set(d, tm.tm_mday, not_a_day, is); ++ checked_set(H, tm.tm_hour, not_a_hour, is); ++ checked_set(M, tm.tm_min, not_a_minute, is); ++ checked_set(s, duration_cast(seconds{tm.tm_sec}), ++ not_a_second, is); ++ } ++ is.setstate(err); ++#else ++ // "%a %b %e %T %Y" ++ auto nm = detail::weekday_names(); ++ auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ checked_set(wd, static_cast(i % 7), not_a_weekday, is); ++ ws(is); ++ nm = detail::month_names(); ++ i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ checked_set(m, static_cast(i % 12 + 1), not_a_month, is); ++ ws(is); ++ int td = not_a_day; ++ read(is, rs{td, 1, 2}); ++ checked_set(d, td, not_a_day, is); ++ ws(is); ++ using dfs = detail::decimal_format_seconds; ++ CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ++ int tH; ++ int tM; ++ long double S{}; ++ read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ++ CharT{':'}, rld{S, 1, w}); ++ checked_set(H, tH, not_a_hour, is); ++ checked_set(M, tM, not_a_minute, is); ++ checked_set(s, round_i(duration{S}), ++ not_a_second, is); ++ ws(is); ++ int tY = not_a_year; ++ read(is, rs{tY, 1, 4u}); ++ checked_set(Y, tY, not_a_year, is); ++#endif ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'x': ++ if (command) ++ { ++ if (modified != CharT{'O'}) ++ { ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ { ++ checked_set(Y, tm.tm_year + 1900, not_a_year, is); ++ checked_set(m, tm.tm_mon + 1, not_a_month, is); ++ checked_set(d, tm.tm_mday, not_a_day, is); ++ } ++ is.setstate(err); ++#else ++ // "%m/%d/%y" ++ int ty = not_a_2digit_year; ++ int tm = not_a_month; ++ int td = not_a_day; ++ read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'}, ++ rs{ty, 1, 2}); ++ checked_set(y, ty, not_a_2digit_year, is); ++ checked_set(m, tm, not_a_month, is); ++ checked_set(d, td, not_a_day, is); ++#endif ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'X': ++ if (command) ++ { ++ if (modified != CharT{'O'}) ++ { ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ { ++ checked_set(H, tm.tm_hour, not_a_hour, is); ++ checked_set(M, tm.tm_min, not_a_minute, is); ++ checked_set(s, duration_cast(seconds{tm.tm_sec}), ++ not_a_second, is); ++ } ++ is.setstate(err); ++#else ++ // "%T" ++ using dfs = detail::decimal_format_seconds; ++ CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ++ int tH = not_a_hour; ++ int tM = not_a_minute; ++ long double S{}; ++ read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ++ CharT{':'}, rld{S, 1, w}); ++ checked_set(H, tH, not_a_hour, is); ++ checked_set(M, tM, not_a_minute, is); ++ checked_set(s, round_i(duration{S}), ++ not_a_second, is); ++#endif ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'C': ++ if (command) ++ { ++ int tC = not_a_century; ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++ { ++#endif ++ read(is, rs{tC, 1, width == -1 ? 2u : static_cast(width)}); ++#if !ONLY_C_LOCALE ++ } ++ else ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ { ++ auto tY = tm.tm_year + 1900; ++ tC = (tY >= 0 ? tY : tY-99) / 100; ++ } ++ is.setstate(err); ++ } ++#endif ++ checked_set(C, tC, not_a_century, is); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'D': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tn = not_a_month; ++ int td = not_a_day; ++ int ty = not_a_2digit_year; ++ read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, ++ ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, ++ rs{ty, 1, 2}); ++ checked_set(y, ty, not_a_2digit_year, is); ++ checked_set(m, tn, not_a_month, is); ++ checked_set(d, td, not_a_day, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'F': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tY = not_a_year; ++ int tn = not_a_month; ++ int td = not_a_day; ++ read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}, ++ CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2}); ++ checked_set(Y, tY, not_a_year, is); ++ checked_set(m, tn, not_a_month, is); ++ checked_set(d, td, not_a_day, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'd': ++ case 'e': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ int td = not_a_day; ++ read(is, rs{td, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(d, td, not_a_day, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ if ((err & ios::failbit) == 0) ++ checked_set(d, tm.tm_mday, not_a_day, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'H': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ int tH = not_a_hour; ++ read(is, ru{tH, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(H, tH, not_a_hour, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(H, tm.tm_hour, not_a_hour, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'I': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tI = not_a_hour_12_value; ++ // reads in an hour into I, but most be in [1, 12] ++ read(is, rs{tI, 1, width == -1 ? 2u : static_cast(width)}); ++ if (!(1 <= tI && tI <= 12)) ++ is.setstate(ios::failbit); ++ checked_set(I, tI, not_a_hour_12_value, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'j': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tj = not_a_doy; ++ read(is, ru{tj, 1, width == -1 ? 3u : static_cast(width)}); ++ checked_set(j, tj, not_a_doy, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'M': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ int tM = not_a_minute; ++ read(is, ru{tM, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(M, tM, not_a_minute, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(M, tm.tm_min, not_a_minute, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'm': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ int tn = not_a_month; ++ read(is, rs{tn, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(m, tn, not_a_month, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(m, tm.tm_mon + 1, not_a_month, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'n': ++ case 't': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ // %n matches a single white space character ++ // %t matches 0 or 1 white space characters ++ auto ic = is.peek(); ++ if (Traits::eq_int_type(ic, Traits::eof())) ++ { ++ ios::iostate err = ios::eofbit; ++ if (*fmt == 'n') ++ err |= ios::failbit; ++ is.setstate(err); ++ break; ++ } ++ if (isspace(ic)) ++ { ++ (void)is.get(); ++ } ++ else if (*fmt == 'n') ++ is.setstate(ios::failbit); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'p': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tp = not_a_ampm; ++#if !ONLY_C_LOCALE ++ tm = std::tm{}; ++ tm.tm_hour = 1; ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ is.setstate(err); ++ if (tm.tm_hour == 1) ++ tp = 0; ++ else if (tm.tm_hour == 13) ++ tp = 1; ++ else ++ is.setstate(err); ++#else ++ auto nm = detail::ampm_names(); ++ auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ tp = static_cast(i); ++#endif ++ checked_set(p, tp, not_a_ampm, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ ++ break; ++ case 'r': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++#if !ONLY_C_LOCALE ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ { ++ checked_set(H, tm.tm_hour, not_a_hour, is); ++ checked_set(M, tm.tm_min, not_a_hour, is); ++ checked_set(s, duration_cast(seconds{tm.tm_sec}), ++ not_a_second, is); ++ } ++ is.setstate(err); ++#else ++ // "%I:%M:%S %p" ++ using dfs = detail::decimal_format_seconds; ++ CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ++ long double S{}; ++ int tI = not_a_hour_12_value; ++ int tM = not_a_minute; ++ read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ++ CharT{':'}, rld{S, 1, w}); ++ checked_set(I, tI, not_a_hour_12_value, is); ++ checked_set(M, tM, not_a_minute, is); ++ checked_set(s, round_i(duration{S}), ++ not_a_second, is); ++ ws(is); ++ auto nm = detail::ampm_names(); ++ auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ++ checked_set(p, static_cast(i), not_a_ampm, is); ++#endif ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'R': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tH = not_a_hour; ++ int tM = not_a_minute; ++ read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'}, ++ ru{tM, 1, 2}, CharT{'\0'}); ++ checked_set(H, tH, not_a_hour, is); ++ checked_set(M, tM, not_a_minute, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'S': ++ if (command) ++ { ++ #if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'E'}) ++#endif ++ { ++ using dfs = detail::decimal_format_seconds; ++ CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ++ long double S{}; ++ read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); ++ checked_set(s, round_i(duration{S}), ++ not_a_second, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'O'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(s, duration_cast(seconds{tm.tm_sec}), ++ not_a_second, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'T': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ using dfs = detail::decimal_format_seconds; ++ CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ++ int tH = not_a_hour; ++ int tM = not_a_minute; ++ long double S{}; ++ read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ++ CharT{':'}, rld{S, 1, w}); ++ checked_set(H, tH, not_a_hour, is); ++ checked_set(M, tM, not_a_minute, is); ++ checked_set(s, round_i(duration{S}), ++ not_a_second, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'Y': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#else ++ if (modified != CharT{'O'}) ++#endif ++ { ++ int tY = not_a_year; ++ read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}); ++ checked_set(Y, tY, not_a_year, is); ++ } ++#if !ONLY_C_LOCALE ++ else if (modified == CharT{'E'}) ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(Y, tm.tm_year + 1900, not_a_year, is); ++ is.setstate(err); ++ } ++#endif ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'y': ++ if (command) ++ { ++#if !ONLY_C_LOCALE ++ if (modified == CharT{}) ++#endif ++ { ++ int ty = not_a_2digit_year; ++ read(is, ru{ty, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(y, ty, not_a_2digit_year, is); ++ } ++#if !ONLY_C_LOCALE ++ else ++ { ++ ios::iostate err = ios::goodbit; ++ f.get(is, nullptr, is, err, &tm, command, fmt+1); ++ if ((err & ios::failbit) == 0) ++ checked_set(Y, tm.tm_year + 1900, not_a_year, is); ++ is.setstate(err); ++ } ++#endif ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'g': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tg = not_a_2digit_year; ++ read(is, ru{tg, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(g, tg, not_a_2digit_year, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'G': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tG = not_a_year; ++ read(is, rs{tG, 1, width == -1 ? 4u : static_cast(width)}); ++ checked_set(G, tG, not_a_year, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'U': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tU = not_a_week_num; ++ read(is, ru{tU, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(U, tU, not_a_week_num, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'V': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tV = not_a_week_num; ++ read(is, ru{tV, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(V, tV, not_a_week_num, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'W': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ int tW = not_a_week_num; ++ read(is, ru{tW, 1, width == -1 ? 2u : static_cast(width)}); ++ checked_set(W, tW, not_a_week_num, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'E': ++ case 'O': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ modified = *fmt; ++ } ++ else ++ { ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ } ++ else ++ read(is, *fmt); ++ break; ++ case '%': ++ if (command) ++ { ++ if (modified == CharT{}) ++ read(is, *fmt); ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ command = fmt; ++ break; ++ case 'z': ++ if (command) ++ { ++ int tH, tM; ++ minutes toff = not_a_offset; ++ bool neg = false; ++ auto ic = is.peek(); ++ if (!Traits::eq_int_type(ic, Traits::eof())) ++ { ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if (c == '-') ++ neg = true; ++ } ++ if (modified == CharT{}) ++ { ++ read(is, rs{tH, 2, 2}); ++ if (!is.fail()) ++ toff = hours{std::abs(tH)}; ++ if (is.good()) ++ { ++ ic = is.peek(); ++ if (!Traits::eq_int_type(ic, Traits::eof())) ++ { ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if ('0' <= c && c <= '9') ++ { ++ read(is, ru{tM, 2, 2}); ++ if (!is.fail()) ++ toff += minutes{tM}; ++ } ++ } ++ } ++ } ++ else ++ { ++ read(is, rs{tH, 1, 2}); ++ if (!is.fail()) ++ toff = hours{std::abs(tH)}; ++ if (is.good()) ++ { ++ ic = is.peek(); ++ if (!Traits::eq_int_type(ic, Traits::eof())) ++ { ++ auto c = static_cast(Traits::to_char_type(ic)); ++ if (c == ':') ++ { ++ (void)is.get(); ++ read(is, ru{tM, 2, 2}); ++ if (!is.fail()) ++ toff += minutes{tM}; ++ } ++ } ++ } ++ } ++ if (neg) ++ toff = -toff; ++ checked_set(temp_offset, toff, not_a_offset, is); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ case 'Z': ++ if (command) ++ { ++ if (modified == CharT{}) ++ { ++ std::basic_string buf; ++ while (is.rdstate() == std::ios::goodbit) ++ { ++ auto i = is.rdbuf()->sgetc(); ++ if (Traits::eq_int_type(i, Traits::eof())) ++ { ++ is.setstate(ios::eofbit); ++ break; ++ } ++ auto wc = Traits::to_char_type(i); ++ auto c = static_cast(wc); ++ // is c a valid time zone name or abbreviation character? ++ if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) || ++ c == '_' || c == '/' || c == '-' || c == '+')) ++ break; ++ buf.push_back(c); ++ is.rdbuf()->sbumpc(); ++ } ++ if (buf.empty()) ++ is.setstate(ios::failbit); ++ checked_set(temp_abbrev, buf, {}, is); ++ } ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ else ++ read(is, *fmt); ++ break; ++ default: ++ if (command) ++ { ++ if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9') ++ { ++ width = static_cast(*fmt) - '0'; ++ while ('0' <= fmt[1] && fmt[1] <= '9') ++ width = 10*width + static_cast(*++fmt) - '0'; ++ } ++ else ++ { ++ if (modified == CharT{}) ++ read(is, CharT{'%'}, width, *fmt); ++ else ++ read(is, CharT{'%'}, width, modified, *fmt); ++ command = nullptr; ++ width = -1; ++ modified = CharT{}; ++ } ++ } ++ else // !command ++ { ++ if (isspace(static_cast(*fmt))) ++ { ++ // space matches 0 or more white space characters ++ if (is.good()) ++ ws(is); ++ } ++ else ++ read(is, *fmt); ++ } ++ break; ++ } ++ } ++ // is.fail() || *fmt == CharT{} ++ if (is.rdstate() == ios::goodbit && command) ++ { ++ if (modified == CharT{}) ++ read(is, CharT{'%'}, width); ++ else ++ read(is, CharT{'%'}, width, modified); ++ } ++ if (!is.fail()) ++ { ++ if (y != not_a_2digit_year) ++ { ++ // Convert y and an optional C to Y ++ if (!(0 <= y && y <= 99)) ++ goto broken; ++ if (C == not_a_century) ++ { ++ if (Y == not_a_year) ++ { ++ if (y >= 69) ++ C = 19; ++ else ++ C = 20; ++ } ++ else ++ { ++ C = (Y >= 0 ? Y : Y-100) / 100; ++ } ++ } ++ int tY; ++ if (C >= 0) ++ tY = 100*C + y; ++ else ++ tY = 100*(C+1) - (y == 0 ? 100 : y); ++ if (Y != not_a_year && Y != tY) ++ goto broken; ++ Y = tY; ++ } ++ if (g != not_a_2digit_year) ++ { ++ // Convert g and an optional C to G ++ if (!(0 <= g && g <= 99)) ++ goto broken; ++ if (C == not_a_century) ++ { ++ if (G == not_a_year) ++ { ++ if (g >= 69) ++ C = 19; ++ else ++ C = 20; ++ } ++ else ++ { ++ C = (G >= 0 ? G : G-100) / 100; ++ } ++ } ++ int tG; ++ if (C >= 0) ++ tG = 100*C + g; ++ else ++ tG = 100*(C+1) - (g == 0 ? 100 : g); ++ if (G != not_a_year && G != tG) ++ goto broken; ++ G = tG; ++ } ++ if (Y < static_cast(year::min()) || Y > static_cast(year::max())) ++ Y = not_a_year; ++ bool computed = false; ++ if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday) ++ { ++ year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) + ++ (Monday-Thursday) + weeks{V-1} + ++ (weekday{static_cast(wd)}-Monday); ++ if (Y == not_a_year) ++ Y = static_cast(ymd_trial.year()); ++ else if (year{Y} != ymd_trial.year()) ++ goto broken; ++ if (m == not_a_month) ++ m = static_cast(static_cast(ymd_trial.month())); ++ else if (month(static_cast(m)) != ymd_trial.month()) ++ goto broken; ++ if (d == not_a_day) ++ d = static_cast(static_cast(ymd_trial.day())); ++ else if (day(static_cast(d)) != ymd_trial.day()) ++ goto broken; ++ computed = true; ++ } ++ if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday) ++ { ++ year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) + ++ weeks{U-1} + ++ (weekday{static_cast(wd)} - Sunday); ++ if (Y == not_a_year) ++ Y = static_cast(ymd_trial.year()); ++ else if (year{Y} != ymd_trial.year()) ++ goto broken; ++ if (m == not_a_month) ++ m = static_cast(static_cast(ymd_trial.month())); ++ else if (month(static_cast(m)) != ymd_trial.month()) ++ goto broken; ++ if (d == not_a_day) ++ d = static_cast(static_cast(ymd_trial.day())); ++ else if (day(static_cast(d)) != ymd_trial.day()) ++ goto broken; ++ computed = true; ++ } ++ if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday) ++ { ++ year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) + ++ weeks{W-1} + ++ (weekday{static_cast(wd)} - Monday); ++ if (Y == not_a_year) ++ Y = static_cast(ymd_trial.year()); ++ else if (year{Y} != ymd_trial.year()) ++ goto broken; ++ if (m == not_a_month) ++ m = static_cast(static_cast(ymd_trial.month())); ++ else if (month(static_cast(m)) != ymd_trial.month()) ++ goto broken; ++ if (d == not_a_day) ++ d = static_cast(static_cast(ymd_trial.day())); ++ else if (day(static_cast(d)) != ymd_trial.day()) ++ goto broken; ++ computed = true; ++ } ++ if (j != not_a_doy && Y != not_a_year) ++ { ++ auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}}; ++ if (m == not_a_month) ++ m = static_cast(static_cast(ymd_trial.month())); ++ else if (month(static_cast(m)) != ymd_trial.month()) ++ goto broken; ++ if (d == not_a_day) ++ d = static_cast(static_cast(ymd_trial.day())); ++ else if (day(static_cast(d)) != ymd_trial.day()) ++ goto broken; ++ j = not_a_doy; ++ } ++ auto ymd = year{Y}/m/d; ++ if (ymd.ok()) ++ { ++ if (wd == not_a_weekday) ++ wd = static_cast((weekday(sys_days(ymd)) - Sunday).count()); ++ else if (wd != static_cast((weekday(sys_days(ymd)) - Sunday).count())) ++ goto broken; ++ if (!computed) ++ { ++ if (G != not_a_year || V != not_a_week_num) ++ { ++ sys_days sd = ymd; ++ auto G_trial = year_month_day{sd + days{3}}.year(); ++ auto start = sys_days((G_trial - years{1})/December/Thursday[last]) + ++ (Monday - Thursday); ++ if (sd < start) ++ { ++ --G_trial; ++ if (V != not_a_week_num) ++ start = sys_days((G_trial - years{1})/December/Thursday[last]) ++ + (Monday - Thursday); ++ } ++ if (G != not_a_year && G != static_cast(G_trial)) ++ goto broken; ++ if (V != not_a_week_num) ++ { ++ auto V_trial = duration_cast(sd - start).count() + 1; ++ if (V != V_trial) ++ goto broken; ++ } ++ } ++ if (U != not_a_week_num) ++ { ++ auto start = sys_days(Sunday[1]/January/ymd.year()); ++ auto U_trial = floor(sys_days(ymd) - start).count() + 1; ++ if (U != U_trial) ++ goto broken; ++ } ++ if (W != not_a_week_num) ++ { ++ auto start = sys_days(Monday[1]/January/ymd.year()); ++ auto W_trial = floor(sys_days(ymd) - start).count() + 1; ++ if (W != W_trial) ++ goto broken; ++ } ++ } ++ } ++ fds.ymd = ymd; ++ if (I != not_a_hour_12_value) ++ { ++ if (!(1 <= I && I <= 12)) ++ goto broken; ++ if (p != not_a_ampm) ++ { ++ // p is in [0, 1] == [AM, PM] ++ // Store trial H in I ++ if (I == 12) ++ --p; ++ I += p*12; ++ // Either set H from I or make sure H and I are consistent ++ if (H == not_a_hour) ++ H = I; ++ else if (I != H) ++ goto broken; ++ } ++ else // p == not_a_ampm ++ { ++ // if H, make sure H and I could be consistent ++ if (H != not_a_hour) ++ { ++ if (I == 12) ++ { ++ if (H != 0 && H != 12) ++ goto broken; ++ } ++ else if (!(I == H || I == H+12)) ++ { ++ goto broken; ++ } ++ } ++ else // I is ambiguous, AM or PM? ++ goto broken; ++ } ++ } ++ if (H != not_a_hour) ++ { ++ fds.has_tod = true; ++ fds.tod = hh_mm_ss{hours{H}}; ++ } ++ if (M != not_a_minute) ++ { ++ fds.has_tod = true; ++ fds.tod.m_ = minutes{M}; ++ } ++ if (s != not_a_second) ++ { ++ fds.has_tod = true; ++ fds.tod.s_ = detail::decimal_format_seconds{s}; ++ } ++ if (j != not_a_doy) ++ { ++ fds.has_tod = true; ++ fds.tod.h_ += hours{days{j}}; ++ } ++ if (wd != not_a_weekday) ++ fds.wd = weekday{static_cast(wd)}; ++ if (abbrev != nullptr) ++ *abbrev = std::move(temp_abbrev); ++ if (offset != nullptr && temp_offset != not_a_offset) ++ *offset = temp_offset; ++ } ++ return is; ++ } ++broken: ++ is.setstate(ios::failbit); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, year& y, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.year().ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ y = fds.ymd.year(); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, month& m, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.month().ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ m = fds.ymd.month(); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, day& d, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.day().ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ d = fds.ymd.day(); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, weekday& wd, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.wd.ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ wd = fds.wd; ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, year_month& ym, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.month().ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ ym = fds.ymd.year()/fds.ymd.month(); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, month_day& md, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.month().ok() || !fds.ymd.day().ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ md = fds.ymd.month()/fds.ymd.day(); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ year_month_day& ymd, std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = std::chrono::seconds; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.ok()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ ymd = fds.ymd; ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ sys_time& tp, std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = typename std::common_type::type; ++ using detail::round_i; ++ std::chrono::minutes offset_local{}; ++ auto offptr = offset ? offset : &offset_local; ++ fields fds{}; ++ fds.has_tod = true; ++ date::from_stream(is, fmt, fds, abbrev, offptr); ++ if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ tp = round_i(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ local_time& tp, std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using CT = typename std::common_type::type; ++ using detail::round_i; ++ fields fds{}; ++ fds.has_tod = true; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ tp = round_i(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); ++ return is; ++} ++ ++template > ++std::basic_istream& ++from_stream(std::basic_istream& is, const CharT* fmt, ++ std::chrono::duration& d, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++{ ++ using Duration = std::chrono::duration; ++ using CT = typename std::common_type::type; ++ using detail::round_i; ++ fields fds{}; ++ date::from_stream(is, fmt, fds, abbrev, offset); ++ if (!fds.has_tod) ++ is.setstate(std::ios::failbit); ++ if (!is.fail()) ++ d = round_i(fds.tod.to_duration()); ++ return is; ++} ++ ++template , ++ class Alloc = std::allocator> ++struct parse_manip ++{ ++ const std::basic_string format_; ++ Parsable& tp_; ++ std::basic_string* abbrev_; ++ std::chrono::minutes* offset_; ++ ++public: ++ parse_manip(std::basic_string format, Parsable& tp, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++ : format_(std::move(format)) ++ , tp_(tp) ++ , abbrev_(abbrev) ++ , offset_(offset) ++ {} ++ ++#if HAS_STRING_VIEW ++ parse_manip(const CharT* format, Parsable& tp, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++ : format_(format) ++ , tp_(tp) ++ , abbrev_(abbrev) ++ , offset_(offset) ++ {} ++ ++ parse_manip(std::basic_string_view format, Parsable& tp, ++ std::basic_string* abbrev = nullptr, ++ std::chrono::minutes* offset = nullptr) ++ : format_(format) ++ , tp_(tp) ++ , abbrev_(abbrev) ++ , offset_(offset) ++ {} ++#endif // HAS_STRING_VIEW ++}; ++ ++template ++std::basic_istream& ++operator>>(std::basic_istream& is, ++ const parse_manip& x) ++{ ++ return date::from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_); ++} ++ ++template ++inline ++auto ++parse(const std::basic_string& format, Parsable& tp) ++ -> decltype(date::from_stream(std::declval&>(), ++ format.c_str(), tp), ++ parse_manip{format, tp}) ++{ ++ return {format, tp}; ++} ++ ++template ++inline ++auto ++parse(const std::basic_string& format, Parsable& tp, ++ std::basic_string& abbrev) ++ -> decltype(date::from_stream(std::declval&>(), ++ format.c_str(), tp, &abbrev), ++ parse_manip{format, tp, &abbrev}) ++{ ++ return {format, tp, &abbrev}; ++} ++ ++template ++inline ++auto ++parse(const std::basic_string& format, Parsable& tp, ++ std::chrono::minutes& offset) ++ -> decltype(date::from_stream(std::declval&>(), ++ format.c_str(), tp, ++ std::declval*>(), ++ &offset), ++ parse_manip{format, tp, nullptr, &offset}) ++{ ++ return {format, tp, nullptr, &offset}; ++} ++ ++template ++inline ++auto ++parse(const std::basic_string& format, Parsable& tp, ++ std::basic_string& abbrev, std::chrono::minutes& offset) ++ -> decltype(date::from_stream(std::declval&>(), ++ format.c_str(), tp, &abbrev, &offset), ++ parse_manip{format, tp, &abbrev, &offset}) ++{ ++ return {format, tp, &abbrev, &offset}; ++} ++ ++// const CharT* formats ++ ++template ++inline ++auto ++parse(const CharT* format, Parsable& tp) ++ -> decltype(date::from_stream(std::declval&>(), format, tp), ++ parse_manip{format, tp}) ++{ ++ return {format, tp}; ++} ++ ++template ++inline ++auto ++parse(const CharT* format, Parsable& tp, std::basic_string& abbrev) ++ -> decltype(date::from_stream(std::declval&>(), format, ++ tp, &abbrev), ++ parse_manip{format, tp, &abbrev}) ++{ ++ return {format, tp, &abbrev}; ++} ++ ++template ++inline ++auto ++parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset) ++ -> decltype(date::from_stream(std::declval&>(), format, ++ tp, std::declval*>(), &offset), ++ parse_manip{format, tp, nullptr, &offset}) ++{ ++ return {format, tp, nullptr, &offset}; ++} ++ ++template ++inline ++auto ++parse(const CharT* format, Parsable& tp, ++ std::basic_string& abbrev, std::chrono::minutes& offset) ++ -> decltype(date::from_stream(std::declval&>(), format, ++ tp, &abbrev, &offset), ++ parse_manip{format, tp, &abbrev, &offset}) ++{ ++ return {format, tp, &abbrev, &offset}; ++} ++ ++// duration streaming ++ ++template ++inline ++std::basic_ostream& ++operator<<(std::basic_ostream& os, ++ const std::chrono::duration& d) ++{ ++ return os << detail::make_string::from(d.count()) + ++ detail::get_units(typename Period::type{}); ++} ++ ++} // namespace date ++ ++#ifdef _MSC_VER ++# pragma warning(pop) ++#endif ++ ++#ifdef __GNUC__ ++# pragma GCC diagnostic pop ++#endif ++ ++#endif // DATE_H +\ No newline at end of file +diff --git a/harness/aws-lc/json.hpp b/harness/aws-lc/json.hpp +new file mode 100644 +index 0000000..4d1a37a +--- /dev/null ++++ b/harness/aws-lc/json.hpp +@@ -0,0 +1,24596 @@ ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++/****************************************************************************\ ++ * Note on documentation: The source files contain links to the online * ++ * documentation of the public API at https://json.nlohmann.me. This URL * ++ * contains the most recent documentation and should also be applicable to * ++ * previous versions; documentation for deprecated functions is not * ++ * removed, but marked deprecated. See "Generate documentation" section in * ++ * file docs/README.md. * ++\****************************************************************************/ ++ ++#ifndef INCLUDE_NLOHMANN_JSON_HPP_ ++#define INCLUDE_NLOHMANN_JSON_HPP_ ++ ++#include // all_of, find, for_each ++#include // nullptr_t, ptrdiff_t, size_t ++#include // hash, less ++#include // initializer_list ++#ifndef JSON_NO_IO ++ #include // istream, ostream ++#endif // JSON_NO_IO ++#include // random_access_iterator_tag ++#include // unique_ptr ++#include // accumulate ++#include // string, stoi, to_string ++#include // declval, forward, move, pair, swap ++#include // vector ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++// This file contains all macro definitions affecting or depending on the ABI ++ ++#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK ++ #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) ++ #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 ++ #warning "Already included a different version of the library!" ++ #endif ++ #endif ++#endif ++ ++#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) ++#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) ++#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) ++ ++#ifndef JSON_DIAGNOSTICS ++ #define JSON_DIAGNOSTICS 0 ++#endif ++ ++#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON ++ #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 ++#endif ++ ++#if JSON_DIAGNOSTICS ++ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag ++#else ++ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS ++#endif ++ ++#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON ++ #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp ++#else ++ #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON ++#endif ++ ++#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION ++ #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 ++#endif ++ ++// Construct the namespace ABI tags component ++#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b ++#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ ++ NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) ++ ++#define NLOHMANN_JSON_ABI_TAGS \ ++ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ ++ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ ++ NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) ++ ++// Construct the namespace version component ++#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ ++ _v ## major ## _ ## minor ## _ ## patch ++#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ ++ NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) ++ ++#if NLOHMANN_JSON_NAMESPACE_NO_VERSION ++#define NLOHMANN_JSON_NAMESPACE_VERSION ++#else ++#define NLOHMANN_JSON_NAMESPACE_VERSION \ ++ NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ ++ NLOHMANN_JSON_VERSION_MINOR, \ ++ NLOHMANN_JSON_VERSION_PATCH) ++#endif ++ ++// Combine namespace components ++#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b ++#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ ++ NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) ++ ++#ifndef NLOHMANN_JSON_NAMESPACE ++#define NLOHMANN_JSON_NAMESPACE \ ++ nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ ++ NLOHMANN_JSON_ABI_TAGS, \ ++ NLOHMANN_JSON_NAMESPACE_VERSION) ++#endif ++ ++#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN ++#define NLOHMANN_JSON_NAMESPACE_BEGIN \ ++ namespace nlohmann \ ++ { \ ++ inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ ++ NLOHMANN_JSON_ABI_TAGS, \ ++ NLOHMANN_JSON_NAMESPACE_VERSION) \ ++ { ++#endif ++ ++#ifndef NLOHMANN_JSON_NAMESPACE_END ++#define NLOHMANN_JSON_NAMESPACE_END \ ++ } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ ++ } // namespace nlohmann ++#endif ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // transform ++#include // array ++#include // forward_list ++#include // inserter, front_inserter, end ++#include // map ++#include // string ++#include // tuple, make_tuple ++#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible ++#include // unordered_map ++#include // pair, declval ++#include // valarray ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // nullptr_t ++#include // exception ++#include // runtime_error ++#include // to_string ++#include // vector ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // array ++#include // size_t ++#include // uint8_t ++#include // string ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // declval, pair ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++template struct make_void ++{ ++ using type = void; ++}; ++template using void_t = typename make_void::type; ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++// https://en.cppreference.com/w/cpp/experimental/is_detected ++struct nonesuch ++{ ++ nonesuch() = delete; ++ ~nonesuch() = delete; ++ nonesuch(nonesuch const&) = delete; ++ nonesuch(nonesuch const&&) = delete; ++ void operator=(nonesuch const&) = delete; ++ void operator=(nonesuch&&) = delete; ++}; ++ ++template class Op, ++ class... Args> ++struct detector ++{ ++ using value_t = std::false_type; ++ using type = Default; ++}; ++ ++template class Op, class... Args> ++struct detector>, Op, Args...> ++{ ++ using value_t = std::true_type; ++ using type = Op; ++}; ++ ++template class Op, class... Args> ++using is_detected = typename detector::value_t; ++ ++template class Op, class... Args> ++struct is_detected_lazy : is_detected { }; ++ ++template class Op, class... Args> ++using detected_t = typename detector::type; ++ ++template class Op, class... Args> ++using detected_or = detector; ++ ++template class Op, class... Args> ++using detected_or_t = typename detected_or::type; ++ ++template class Op, class... Args> ++using is_detected_exact = std::is_same>; ++ ++template class Op, class... Args> ++using is_detected_convertible = ++ std::is_convertible, To>; ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++ ++ ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson ++// SPDX-License-Identifier: MIT ++ ++/* Hedley - https://nemequ.github.io/hedley ++ * Created by Evan Nemerson ++ */ ++ ++#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) ++#if defined(JSON_HEDLEY_VERSION) ++ #undef JSON_HEDLEY_VERSION ++#endif ++#define JSON_HEDLEY_VERSION 15 ++ ++#if defined(JSON_HEDLEY_STRINGIFY_EX) ++ #undef JSON_HEDLEY_STRINGIFY_EX ++#endif ++#define JSON_HEDLEY_STRINGIFY_EX(x) #x ++ ++#if defined(JSON_HEDLEY_STRINGIFY) ++ #undef JSON_HEDLEY_STRINGIFY ++#endif ++#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) ++ ++#if defined(JSON_HEDLEY_CONCAT_EX) ++ #undef JSON_HEDLEY_CONCAT_EX ++#endif ++#define JSON_HEDLEY_CONCAT_EX(a,b) a##b ++ ++#if defined(JSON_HEDLEY_CONCAT) ++ #undef JSON_HEDLEY_CONCAT ++#endif ++#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) ++ ++#if defined(JSON_HEDLEY_CONCAT3_EX) ++ #undef JSON_HEDLEY_CONCAT3_EX ++#endif ++#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c ++ ++#if defined(JSON_HEDLEY_CONCAT3) ++ #undef JSON_HEDLEY_CONCAT3 ++#endif ++#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) ++ ++#if defined(JSON_HEDLEY_VERSION_ENCODE) ++ #undef JSON_HEDLEY_VERSION_ENCODE ++#endif ++#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) ++ ++#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) ++ #undef JSON_HEDLEY_VERSION_DECODE_MAJOR ++#endif ++#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) ++ ++#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) ++ #undef JSON_HEDLEY_VERSION_DECODE_MINOR ++#endif ++#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) ++ ++#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) ++ #undef JSON_HEDLEY_VERSION_DECODE_REVISION ++#endif ++#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) ++ ++#if defined(JSON_HEDLEY_GNUC_VERSION) ++ #undef JSON_HEDLEY_GNUC_VERSION ++#endif ++#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) ++ #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) ++#elif defined(__GNUC__) ++ #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) ++ #undef JSON_HEDLEY_GNUC_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_GNUC_VERSION) ++ #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_MSVC_VERSION) ++ #undef JSON_HEDLEY_MSVC_VERSION ++#endif ++#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) ++ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) ++#elif defined(_MSC_FULL_VER) && !defined(__ICL) ++ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) ++#elif defined(_MSC_VER) && !defined(__ICL) ++ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) ++ #undef JSON_HEDLEY_MSVC_VERSION_CHECK ++#endif ++#if !defined(JSON_HEDLEY_MSVC_VERSION) ++ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) ++#elif defined(_MSC_VER) && (_MSC_VER >= 1400) ++ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) ++#elif defined(_MSC_VER) && (_MSC_VER >= 1200) ++ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) ++#else ++ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) ++#endif ++ ++#if defined(JSON_HEDLEY_INTEL_VERSION) ++ #undef JSON_HEDLEY_INTEL_VERSION ++#endif ++#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) ++ #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) ++#elif defined(__INTEL_COMPILER) && !defined(__ICL) ++ #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) ++ #undef JSON_HEDLEY_INTEL_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_INTEL_VERSION) ++ #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_INTEL_CL_VERSION) ++ #undef JSON_HEDLEY_INTEL_CL_VERSION ++#endif ++#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) ++ #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) ++ #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_INTEL_CL_VERSION) ++ #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_PGI_VERSION) ++ #undef JSON_HEDLEY_PGI_VERSION ++#endif ++#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) ++ #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) ++#endif ++ ++#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) ++ #undef JSON_HEDLEY_PGI_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_PGI_VERSION) ++ #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_SUNPRO_VERSION) ++ #undef JSON_HEDLEY_SUNPRO_VERSION ++#endif ++#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) ++ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) ++#elif defined(__SUNPRO_C) ++ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) ++#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) ++ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) ++#elif defined(__SUNPRO_CC) ++ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) ++#endif ++ ++#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) ++ #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_SUNPRO_VERSION) ++ #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) ++ #undef JSON_HEDLEY_EMSCRIPTEN_VERSION ++#endif ++#if defined(__EMSCRIPTEN__) ++ #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) ++#endif ++ ++#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) ++ #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) ++ #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_ARM_VERSION) ++ #undef JSON_HEDLEY_ARM_VERSION ++#endif ++#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) ++ #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) ++#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) ++ #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) ++#endif ++ ++#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) ++ #undef JSON_HEDLEY_ARM_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_ARM_VERSION) ++ #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_IBM_VERSION) ++ #undef JSON_HEDLEY_IBM_VERSION ++#endif ++#if defined(__ibmxl__) ++ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) ++#elif defined(__xlC__) && defined(__xlC_ver__) ++ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) ++#elif defined(__xlC__) ++ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) ++ #undef JSON_HEDLEY_IBM_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_IBM_VERSION) ++ #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_VERSION) ++ #undef JSON_HEDLEY_TI_VERSION ++#endif ++#if \ ++ defined(__TI_COMPILER_VERSION__) && \ ++ ( \ ++ defined(__TMS470__) || defined(__TI_ARM__) || \ ++ defined(__MSP430__) || \ ++ defined(__TMS320C2000__) \ ++ ) ++#if (__TI_COMPILER_VERSION__ >= 16000000) ++ #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++#endif ++ ++#if defined(JSON_HEDLEY_TI_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_VERSION) ++ #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL2000_VERSION) ++ #undef JSON_HEDLEY_TI_CL2000_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) ++ #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_CL2000_VERSION) ++ #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL430_VERSION) ++ #undef JSON_HEDLEY_TI_CL430_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) ++ #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_CL430_VERSION) ++ #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) ++ #undef JSON_HEDLEY_TI_ARMCL_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) ++ #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) ++ #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL6X_VERSION) ++ #undef JSON_HEDLEY_TI_CL6X_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) ++ #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_CL6X_VERSION) ++ #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL7X_VERSION) ++ #undef JSON_HEDLEY_TI_CL7X_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) ++ #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_CL7X_VERSION) ++ #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) ++ #undef JSON_HEDLEY_TI_CLPRU_VERSION ++#endif ++#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) ++ #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) ++#endif ++ ++#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) ++ #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) ++ #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_CRAY_VERSION) ++ #undef JSON_HEDLEY_CRAY_VERSION ++#endif ++#if defined(_CRAYC) ++ #if defined(_RELEASE_PATCHLEVEL) ++ #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) ++ #else ++ #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) ++ #endif ++#endif ++ ++#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) ++ #undef JSON_HEDLEY_CRAY_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_CRAY_VERSION) ++ #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_IAR_VERSION) ++ #undef JSON_HEDLEY_IAR_VERSION ++#endif ++#if defined(__IAR_SYSTEMS_ICC__) ++ #if __VER__ > 1000 ++ #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) ++ #else ++ #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) ++ #endif ++#endif ++ ++#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) ++ #undef JSON_HEDLEY_IAR_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_IAR_VERSION) ++ #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_TINYC_VERSION) ++ #undef JSON_HEDLEY_TINYC_VERSION ++#endif ++#if defined(__TINYC__) ++ #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) ++#endif ++ ++#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) ++ #undef JSON_HEDLEY_TINYC_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_TINYC_VERSION) ++ #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_DMC_VERSION) ++ #undef JSON_HEDLEY_DMC_VERSION ++#endif ++#if defined(__DMC__) ++ #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) ++#endif ++ ++#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) ++ #undef JSON_HEDLEY_DMC_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_DMC_VERSION) ++ #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_COMPCERT_VERSION) ++ #undef JSON_HEDLEY_COMPCERT_VERSION ++#endif ++#if defined(__COMPCERT_VERSION__) ++ #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) ++#endif ++ ++#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) ++ #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_COMPCERT_VERSION) ++ #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_PELLES_VERSION) ++ #undef JSON_HEDLEY_PELLES_VERSION ++#endif ++#if defined(__POCC__) ++ #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) ++#endif ++ ++#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) ++ #undef JSON_HEDLEY_PELLES_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_PELLES_VERSION) ++ #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_MCST_LCC_VERSION) ++ #undef JSON_HEDLEY_MCST_LCC_VERSION ++#endif ++#if defined(__LCC__) && defined(__LCC_MINOR__) ++ #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) ++#endif ++ ++#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) ++ #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_MCST_LCC_VERSION) ++ #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_VERSION) ++ #undef JSON_HEDLEY_GCC_VERSION ++#endif ++#if \ ++ defined(JSON_HEDLEY_GNUC_VERSION) && \ ++ !defined(__clang__) && \ ++ !defined(JSON_HEDLEY_INTEL_VERSION) && \ ++ !defined(JSON_HEDLEY_PGI_VERSION) && \ ++ !defined(JSON_HEDLEY_ARM_VERSION) && \ ++ !defined(JSON_HEDLEY_CRAY_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ ++ !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ ++ !defined(__COMPCERT__) && \ ++ !defined(JSON_HEDLEY_MCST_LCC_VERSION) ++ #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) ++ #undef JSON_HEDLEY_GCC_VERSION_CHECK ++#endif ++#if defined(JSON_HEDLEY_GCC_VERSION) ++ #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) ++#else ++ #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) ++ #undef JSON_HEDLEY_HAS_ATTRIBUTE ++#endif ++#if \ ++ defined(__has_attribute) && \ ++ ( \ ++ (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ ++ ) ++# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) ++#else ++# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) ++ #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE ++#endif ++#if defined(__has_attribute) ++ #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) ++ #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE ++#endif ++#if defined(__has_attribute) ++ #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) ++#else ++ #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) ++ #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE ++#endif ++#if \ ++ defined(__has_cpp_attribute) && \ ++ defined(__cplusplus) && \ ++ (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) ++ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) ++#else ++ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) ++ #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS ++#endif ++#if !defined(__cplusplus) || !defined(__has_cpp_attribute) ++ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) ++#elif \ ++ !defined(JSON_HEDLEY_PGI_VERSION) && \ ++ !defined(JSON_HEDLEY_IAR_VERSION) && \ ++ (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ ++ (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) ++ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) ++#else ++ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) ++ #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE ++#endif ++#if defined(__has_cpp_attribute) && defined(__cplusplus) ++ #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) ++ #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE ++#endif ++#if defined(__has_cpp_attribute) && defined(__cplusplus) ++ #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) ++#else ++ #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_BUILTIN) ++ #undef JSON_HEDLEY_HAS_BUILTIN ++#endif ++#if defined(__has_builtin) ++ #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) ++#else ++ #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) ++ #undef JSON_HEDLEY_GNUC_HAS_BUILTIN ++#endif ++#if defined(__has_builtin) ++ #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) ++ #undef JSON_HEDLEY_GCC_HAS_BUILTIN ++#endif ++#if defined(__has_builtin) ++ #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) ++#else ++ #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_FEATURE) ++ #undef JSON_HEDLEY_HAS_FEATURE ++#endif ++#if defined(__has_feature) ++ #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) ++#else ++ #define JSON_HEDLEY_HAS_FEATURE(feature) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) ++ #undef JSON_HEDLEY_GNUC_HAS_FEATURE ++#endif ++#if defined(__has_feature) ++ #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) ++ #undef JSON_HEDLEY_GCC_HAS_FEATURE ++#endif ++#if defined(__has_feature) ++ #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) ++#else ++ #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_EXTENSION) ++ #undef JSON_HEDLEY_HAS_EXTENSION ++#endif ++#if defined(__has_extension) ++ #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) ++#else ++ #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) ++ #undef JSON_HEDLEY_GNUC_HAS_EXTENSION ++#endif ++#if defined(__has_extension) ++ #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) ++ #undef JSON_HEDLEY_GCC_HAS_EXTENSION ++#endif ++#if defined(__has_extension) ++ #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) ++#else ++ #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) ++ #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE ++#endif ++#if defined(__has_declspec_attribute) ++ #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) ++#else ++ #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) ++ #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE ++#endif ++#if defined(__has_declspec_attribute) ++ #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) ++ #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE ++#endif ++#if defined(__has_declspec_attribute) ++ #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) ++#else ++ #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_HAS_WARNING) ++ #undef JSON_HEDLEY_HAS_WARNING ++#endif ++#if defined(__has_warning) ++ #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) ++#else ++ #define JSON_HEDLEY_HAS_WARNING(warning) (0) ++#endif ++ ++#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) ++ #undef JSON_HEDLEY_GNUC_HAS_WARNING ++#endif ++#if defined(__has_warning) ++ #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) ++#else ++ #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_GCC_HAS_WARNING) ++ #undef JSON_HEDLEY_GCC_HAS_WARNING ++#endif ++#if defined(__has_warning) ++ #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) ++#else ++ #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if \ ++ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ ++ defined(__clang__) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ ++ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ ++ (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) ++ #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) ++#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) ++ #define JSON_HEDLEY_PRAGMA(value) __pragma(value) ++#else ++ #define JSON_HEDLEY_PRAGMA(value) ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) ++ #undef JSON_HEDLEY_DIAGNOSTIC_PUSH ++#endif ++#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) ++ #undef JSON_HEDLEY_DIAGNOSTIC_POP ++#endif ++#if defined(__clang__) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") ++#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) ++ #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) ++#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") ++#elif \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") ++ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_PUSH ++ #define JSON_HEDLEY_DIAGNOSTIC_POP ++#endif ++ ++/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for ++ HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ ++#endif ++#if defined(__cplusplus) ++# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") ++# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") ++# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") ++# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ ++ _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ ++ _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ ++ xpr \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# else ++# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ ++ _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ ++ xpr \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# endif ++# else ++# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ ++ xpr \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# endif ++# endif ++#endif ++#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x ++#endif ++ ++#if defined(JSON_HEDLEY_CONST_CAST) ++ #undef JSON_HEDLEY_CONST_CAST ++#endif ++#if defined(__cplusplus) ++# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) ++#elif \ ++ JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ ++ ((T) (expr)); \ ++ JSON_HEDLEY_DIAGNOSTIC_POP \ ++ })) ++#else ++# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) ++#endif ++ ++#if defined(JSON_HEDLEY_REINTERPRET_CAST) ++ #undef JSON_HEDLEY_REINTERPRET_CAST ++#endif ++#if defined(__cplusplus) ++ #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) ++#else ++ #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) ++#endif ++ ++#if defined(JSON_HEDLEY_STATIC_CAST) ++ #undef JSON_HEDLEY_STATIC_CAST ++#endif ++#if defined(__cplusplus) ++ #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) ++#else ++ #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) ++#endif ++ ++#if defined(JSON_HEDLEY_CPP_CAST) ++ #undef JSON_HEDLEY_CPP_CAST ++#endif ++#if defined(__cplusplus) ++# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") ++# define JSON_HEDLEY_CPP_CAST(T, expr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ ++ ((T) (expr)) \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) ++# define JSON_HEDLEY_CPP_CAST(T, expr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("diag_suppress=Pe137") \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# else ++# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) ++# endif ++#else ++# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") ++#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") ++#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") ++#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) ++#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") ++#elif \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") ++#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") ++#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") ++#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) ++#elif \ ++ JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") ++#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") ++#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") ++#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") ++#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) ++#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") ++#elif \ ++ JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") ++#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") ++#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL ++#endif ++ ++#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) ++ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") ++#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") ++#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) ++#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") ++#else ++ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION ++#endif ++ ++#if defined(JSON_HEDLEY_DEPRECATED) ++ #undef JSON_HEDLEY_DEPRECATED ++#endif ++#if defined(JSON_HEDLEY_DEPRECATED_FOR) ++ #undef JSON_HEDLEY_DEPRECATED_FOR ++#endif ++#if \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) ++#elif \ ++ (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) ++#elif defined(__cplusplus) && (__cplusplus >= 201402L) ++ #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) ++#elif \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) ++ #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ ++ JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") ++#else ++ #define JSON_HEDLEY_DEPRECATED(since) ++ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) ++#endif ++ ++#if defined(JSON_HEDLEY_UNAVAILABLE) ++ #undef JSON_HEDLEY_UNAVAILABLE ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) ++#else ++ #define JSON_HEDLEY_UNAVAILABLE(available_since) ++#endif ++ ++#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) ++ #undef JSON_HEDLEY_WARN_UNUSED_RESULT ++#endif ++#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) ++ #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) ++#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) ++#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) ++#elif defined(_Check_return_) /* SAL */ ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ ++#else ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT ++ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) ++#endif ++ ++#if defined(JSON_HEDLEY_SENTINEL) ++ #undef JSON_HEDLEY_SENTINEL ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) ++#else ++ #define JSON_HEDLEY_SENTINEL(position) ++#endif ++ ++#if defined(JSON_HEDLEY_NO_RETURN) ++ #undef JSON_HEDLEY_NO_RETURN ++#endif ++#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_NO_RETURN __noreturn ++#elif \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) ++#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L ++ #define JSON_HEDLEY_NO_RETURN _Noreturn ++#elif defined(__cplusplus) && (__cplusplus >= 201103L) ++ #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) ++#elif \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) ++ #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) ++ #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) ++#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) ++ #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") ++#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) ++ #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) ++ #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) ++#else ++ #define JSON_HEDLEY_NO_RETURN ++#endif ++ ++#if defined(JSON_HEDLEY_NO_ESCAPE) ++ #undef JSON_HEDLEY_NO_ESCAPE ++#endif ++#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) ++ #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) ++#else ++ #define JSON_HEDLEY_NO_ESCAPE ++#endif ++ ++#if defined(JSON_HEDLEY_UNREACHABLE) ++ #undef JSON_HEDLEY_UNREACHABLE ++#endif ++#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) ++ #undef JSON_HEDLEY_UNREACHABLE_RETURN ++#endif ++#if defined(JSON_HEDLEY_ASSUME) ++ #undef JSON_HEDLEY_ASSUME ++#endif ++#if \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_ASSUME(expr) __assume(expr) ++#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) ++ #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) ++#elif \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) ++ #if defined(__cplusplus) ++ #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) ++ #else ++ #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) ++ #endif ++#endif ++#if \ ++ (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ ++ JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() ++#elif defined(JSON_HEDLEY_ASSUME) ++ #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) ++#endif ++#if !defined(JSON_HEDLEY_ASSUME) ++ #if defined(JSON_HEDLEY_UNREACHABLE) ++ #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) ++ #else ++ #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) ++ #endif ++#endif ++#if defined(JSON_HEDLEY_UNREACHABLE) ++ #if \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) ++ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) ++ #else ++ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() ++ #endif ++#else ++ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) ++#endif ++#if !defined(JSON_HEDLEY_UNREACHABLE) ++ #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) ++#endif ++ ++JSON_HEDLEY_DIAGNOSTIC_PUSH ++#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") ++ #pragma clang diagnostic ignored "-Wpedantic" ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) ++ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" ++#endif ++#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) ++ #if defined(__clang__) ++ #pragma clang diagnostic ignored "-Wvariadic-macros" ++ #elif defined(JSON_HEDLEY_GCC_VERSION) ++ #pragma GCC diagnostic ignored "-Wvariadic-macros" ++ #endif ++#endif ++#if defined(JSON_HEDLEY_NON_NULL) ++ #undef JSON_HEDLEY_NON_NULL ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) ++ #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) ++#else ++ #define JSON_HEDLEY_NON_NULL(...) ++#endif ++JSON_HEDLEY_DIAGNOSTIC_POP ++ ++#if defined(JSON_HEDLEY_PRINTF_FORMAT) ++ #undef JSON_HEDLEY_PRINTF_FORMAT ++#endif ++#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) ++ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) ++#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) ++ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) ++#elif \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) ++ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) ++#else ++ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) ++#endif ++ ++#if defined(JSON_HEDLEY_CONSTEXPR) ++ #undef JSON_HEDLEY_CONSTEXPR ++#endif ++#if defined(__cplusplus) ++ #if __cplusplus >= 201103L ++ #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) ++ #endif ++#endif ++#if !defined(JSON_HEDLEY_CONSTEXPR) ++ #define JSON_HEDLEY_CONSTEXPR ++#endif ++ ++#if defined(JSON_HEDLEY_PREDICT) ++ #undef JSON_HEDLEY_PREDICT ++#endif ++#if defined(JSON_HEDLEY_LIKELY) ++ #undef JSON_HEDLEY_LIKELY ++#endif ++#if defined(JSON_HEDLEY_UNLIKELY) ++ #undef JSON_HEDLEY_UNLIKELY ++#endif ++#if defined(JSON_HEDLEY_UNPREDICTABLE) ++ #undef JSON_HEDLEY_UNPREDICTABLE ++#endif ++#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) ++ #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) ++#endif ++#if \ ++ (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) ++# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) ++# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) ++# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) ++# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) ++#elif \ ++ (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ ++ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ ++ (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) ++# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ ++ (__extension__ ({ \ ++ double hedley_probability_ = (probability); \ ++ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ ++ })) ++# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ ++ (__extension__ ({ \ ++ double hedley_probability_ = (probability); \ ++ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ ++ })) ++# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) ++# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) ++#else ++# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) ++# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) ++# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) ++# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) ++# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) ++#endif ++#if !defined(JSON_HEDLEY_UNPREDICTABLE) ++ #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) ++#endif ++ ++#if defined(JSON_HEDLEY_MALLOC) ++ #undef JSON_HEDLEY_MALLOC ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) ++ #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_MALLOC __declspec(restrict) ++#else ++ #define JSON_HEDLEY_MALLOC ++#endif ++ ++#if defined(JSON_HEDLEY_PURE) ++ #undef JSON_HEDLEY_PURE ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++# define JSON_HEDLEY_PURE __attribute__((__pure__)) ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) ++# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") ++#elif defined(__cplusplus) && \ ++ ( \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ ++ ) ++# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") ++#else ++# define JSON_HEDLEY_PURE ++#endif ++ ++#if defined(JSON_HEDLEY_CONST) ++ #undef JSON_HEDLEY_CONST ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_CONST __attribute__((__const__)) ++#elif \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) ++ #define JSON_HEDLEY_CONST _Pragma("no_side_effect") ++#else ++ #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE ++#endif ++ ++#if defined(JSON_HEDLEY_RESTRICT) ++ #undef JSON_HEDLEY_RESTRICT ++#endif ++#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) ++ #define JSON_HEDLEY_RESTRICT restrict ++#elif \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ ++ defined(__clang__) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_RESTRICT __restrict ++#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) ++ #define JSON_HEDLEY_RESTRICT _Restrict ++#else ++ #define JSON_HEDLEY_RESTRICT ++#endif ++ ++#if defined(JSON_HEDLEY_INLINE) ++ #undef JSON_HEDLEY_INLINE ++#endif ++#if \ ++ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ ++ (defined(__cplusplus) && (__cplusplus >= 199711L)) ++ #define JSON_HEDLEY_INLINE inline ++#elif \ ++ defined(JSON_HEDLEY_GCC_VERSION) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) ++ #define JSON_HEDLEY_INLINE __inline__ ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_INLINE __inline ++#else ++ #define JSON_HEDLEY_INLINE ++#endif ++ ++#if defined(JSON_HEDLEY_ALWAYS_INLINE) ++ #undef JSON_HEDLEY_ALWAYS_INLINE ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) ++# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++# define JSON_HEDLEY_ALWAYS_INLINE __forceinline ++#elif defined(__cplusplus) && \ ++ ( \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ ++ ) ++# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") ++#else ++# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE ++#endif ++ ++#if defined(JSON_HEDLEY_NEVER_INLINE) ++ #undef JSON_HEDLEY_NEVER_INLINE ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ ++ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ ++ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ ++ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ ++ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ ++ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ ++ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ ++ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) ++ #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) ++#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) ++ #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") ++#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) ++ #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++ #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") ++#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) ++ #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) ++ #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) ++#else ++ #define JSON_HEDLEY_NEVER_INLINE ++#endif ++ ++#if defined(JSON_HEDLEY_PRIVATE) ++ #undef JSON_HEDLEY_PRIVATE ++#endif ++#if defined(JSON_HEDLEY_PUBLIC) ++ #undef JSON_HEDLEY_PUBLIC ++#endif ++#if defined(JSON_HEDLEY_IMPORT) ++ #undef JSON_HEDLEY_IMPORT ++#endif ++#if defined(_WIN32) || defined(__CYGWIN__) ++# define JSON_HEDLEY_PRIVATE ++# define JSON_HEDLEY_PUBLIC __declspec(dllexport) ++# define JSON_HEDLEY_IMPORT __declspec(dllimport) ++#else ++# if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ ++ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ ++ ( \ ++ defined(__TI_EABI__) && \ ++ ( \ ++ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ ++ ) \ ++ ) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) ++# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) ++# else ++# define JSON_HEDLEY_PRIVATE ++# define JSON_HEDLEY_PUBLIC ++# endif ++# define JSON_HEDLEY_IMPORT extern ++#endif ++ ++#if defined(JSON_HEDLEY_NO_THROW) ++ #undef JSON_HEDLEY_NO_THROW ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) ++ #define JSON_HEDLEY_NO_THROW __declspec(nothrow) ++#else ++ #define JSON_HEDLEY_NO_THROW ++#endif ++ ++#if defined(JSON_HEDLEY_FALL_THROUGH) ++ #undef JSON_HEDLEY_FALL_THROUGH ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) ++#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) ++ #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) ++#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) ++ #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) ++#elif defined(__fallthrough) /* SAL */ ++ #define JSON_HEDLEY_FALL_THROUGH __fallthrough ++#else ++ #define JSON_HEDLEY_FALL_THROUGH ++#endif ++ ++#if defined(JSON_HEDLEY_RETURNS_NON_NULL) ++ #undef JSON_HEDLEY_RETURNS_NON_NULL ++#endif ++#if \ ++ JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) ++#elif defined(_Ret_notnull_) /* SAL */ ++ #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ ++#else ++ #define JSON_HEDLEY_RETURNS_NON_NULL ++#endif ++ ++#if defined(JSON_HEDLEY_ARRAY_PARAM) ++ #undef JSON_HEDLEY_ARRAY_PARAM ++#endif ++#if \ ++ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ ++ !defined(__STDC_NO_VLA__) && \ ++ !defined(__cplusplus) && \ ++ !defined(JSON_HEDLEY_PGI_VERSION) && \ ++ !defined(JSON_HEDLEY_TINYC_VERSION) ++ #define JSON_HEDLEY_ARRAY_PARAM(name) (name) ++#else ++ #define JSON_HEDLEY_ARRAY_PARAM(name) ++#endif ++ ++#if defined(JSON_HEDLEY_IS_CONSTANT) ++ #undef JSON_HEDLEY_IS_CONSTANT ++#endif ++#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) ++ #undef JSON_HEDLEY_REQUIRE_CONSTEXPR ++#endif ++/* JSON_HEDLEY_IS_CONSTEXPR_ is for ++ HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ ++#if defined(JSON_HEDLEY_IS_CONSTEXPR_) ++ #undef JSON_HEDLEY_IS_CONSTEXPR_ ++#endif ++#if \ ++ JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ ++ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ ++ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ ++ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ ++ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) ++ #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) ++#endif ++#if !defined(__cplusplus) ++# if \ ++ JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ ++ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ ++ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) ++#if defined(__INTPTR_TYPE__) ++ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) ++#else ++ #include ++ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) ++#endif ++# elif \ ++ ( \ ++ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ ++ !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ ++ !defined(JSON_HEDLEY_PGI_VERSION) && \ ++ !defined(JSON_HEDLEY_IAR_VERSION)) || \ ++ (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ ++ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ ++ JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) ++#if defined(__INTPTR_TYPE__) ++ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) ++#else ++ #include ++ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) ++#endif ++# elif \ ++ defined(JSON_HEDLEY_GCC_VERSION) || \ ++ defined(JSON_HEDLEY_INTEL_VERSION) || \ ++ defined(JSON_HEDLEY_TINYC_VERSION) || \ ++ defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ ++ JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ ++ defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ ++ defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ ++ defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ ++ defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ ++ defined(__clang__) ++# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ ++ sizeof(void) != \ ++ sizeof(*( \ ++ 1 ? \ ++ ((void*) ((expr) * 0L) ) : \ ++((struct { char v[sizeof(void) * 2]; } *) 1) \ ++ ) \ ++ ) \ ++ ) ++# endif ++#endif ++#if defined(JSON_HEDLEY_IS_CONSTEXPR_) ++ #if !defined(JSON_HEDLEY_IS_CONSTANT) ++ #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) ++ #endif ++ #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) ++#else ++ #if !defined(JSON_HEDLEY_IS_CONSTANT) ++ #define JSON_HEDLEY_IS_CONSTANT(expr) (0) ++ #endif ++ #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) ++#endif ++ ++#if defined(JSON_HEDLEY_BEGIN_C_DECLS) ++ #undef JSON_HEDLEY_BEGIN_C_DECLS ++#endif ++#if defined(JSON_HEDLEY_END_C_DECLS) ++ #undef JSON_HEDLEY_END_C_DECLS ++#endif ++#if defined(JSON_HEDLEY_C_DECL) ++ #undef JSON_HEDLEY_C_DECL ++#endif ++#if defined(__cplusplus) ++ #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { ++ #define JSON_HEDLEY_END_C_DECLS } ++ #define JSON_HEDLEY_C_DECL extern "C" ++#else ++ #define JSON_HEDLEY_BEGIN_C_DECLS ++ #define JSON_HEDLEY_END_C_DECLS ++ #define JSON_HEDLEY_C_DECL ++#endif ++ ++#if defined(JSON_HEDLEY_STATIC_ASSERT) ++ #undef JSON_HEDLEY_STATIC_ASSERT ++#endif ++#if \ ++ !defined(__cplusplus) && ( \ ++ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ ++ (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ ++ defined(_Static_assert) \ ++ ) ++# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) ++#elif \ ++ (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) ++#else ++# define JSON_HEDLEY_STATIC_ASSERT(expr, message) ++#endif ++ ++#if defined(JSON_HEDLEY_NULL) ++ #undef JSON_HEDLEY_NULL ++#endif ++#if defined(__cplusplus) ++ #if __cplusplus >= 201103L ++ #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) ++ #elif defined(NULL) ++ #define JSON_HEDLEY_NULL NULL ++ #else ++ #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) ++ #endif ++#elif defined(NULL) ++ #define JSON_HEDLEY_NULL NULL ++#else ++ #define JSON_HEDLEY_NULL ((void*) 0) ++#endif ++ ++#if defined(JSON_HEDLEY_MESSAGE) ++ #undef JSON_HEDLEY_MESSAGE ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") ++# define JSON_HEDLEY_MESSAGE(msg) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ ++ JSON_HEDLEY_PRAGMA(message msg) \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++#elif \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) ++#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) ++# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) ++#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) ++# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) ++#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) ++# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) ++#else ++# define JSON_HEDLEY_MESSAGE(msg) ++#endif ++ ++#if defined(JSON_HEDLEY_WARNING) ++ #undef JSON_HEDLEY_WARNING ++#endif ++#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") ++# define JSON_HEDLEY_WARNING(msg) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ ++ JSON_HEDLEY_PRAGMA(clang warning msg) \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++#elif \ ++ JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ ++ JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ ++ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) ++# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) ++#elif \ ++ JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) ++#else ++# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) ++#endif ++ ++#if defined(JSON_HEDLEY_REQUIRE) ++ #undef JSON_HEDLEY_REQUIRE ++#endif ++#if defined(JSON_HEDLEY_REQUIRE_MSG) ++ #undef JSON_HEDLEY_REQUIRE_MSG ++#endif ++#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) ++# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") ++# define JSON_HEDLEY_REQUIRE(expr) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ ++ __attribute__((diagnose_if(!(expr), #expr, "error"))) \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ ++ __attribute__((diagnose_if(!(expr), msg, "error"))) \ ++ JSON_HEDLEY_DIAGNOSTIC_POP ++# else ++# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) ++# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) ++# endif ++#else ++# define JSON_HEDLEY_REQUIRE(expr) ++# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) ++#endif ++ ++#if defined(JSON_HEDLEY_FLAGS) ++ #undef JSON_HEDLEY_FLAGS ++#endif ++#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) ++ #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) ++#else ++ #define JSON_HEDLEY_FLAGS ++#endif ++ ++#if defined(JSON_HEDLEY_FLAGS_CAST) ++ #undef JSON_HEDLEY_FLAGS_CAST ++#endif ++#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) ++# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ ++ JSON_HEDLEY_DIAGNOSTIC_PUSH \ ++ _Pragma("warning(disable:188)") \ ++ ((T) (expr)); \ ++ JSON_HEDLEY_DIAGNOSTIC_POP \ ++ })) ++#else ++# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) ++#endif ++ ++#if defined(JSON_HEDLEY_EMPTY_BASES) ++ #undef JSON_HEDLEY_EMPTY_BASES ++#endif ++#if \ ++ (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ ++ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) ++ #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) ++#else ++ #define JSON_HEDLEY_EMPTY_BASES ++#endif ++ ++/* Remaining macros are deprecated. */ ++ ++#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) ++ #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK ++#endif ++#if defined(__clang__) ++ #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) ++#else ++ #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) ++#endif ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) ++ #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE ++#endif ++#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) ++ #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE ++#endif ++#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) ++ #undef JSON_HEDLEY_CLANG_HAS_BUILTIN ++#endif ++#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) ++ #undef JSON_HEDLEY_CLANG_HAS_FEATURE ++#endif ++#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) ++ #undef JSON_HEDLEY_CLANG_HAS_EXTENSION ++#endif ++#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) ++ #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE ++#endif ++#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) ++ ++#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) ++ #undef JSON_HEDLEY_CLANG_HAS_WARNING ++#endif ++#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) ++ ++#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ ++ ++ ++// This file contains all internal macro definitions (except those affecting ABI) ++// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them ++ ++// #include ++ ++ ++// exclude unsupported compilers ++#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) ++ #if defined(__clang__) ++ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 ++ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" ++ #endif ++ #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) ++ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 ++ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" ++ #endif ++ #endif ++#endif ++ ++// C++ language standard detection ++// if the user manually specified the used c++ version this is skipped ++#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) ++ #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) ++ #define JSON_HAS_CPP_20 ++ #define JSON_HAS_CPP_17 ++ #define JSON_HAS_CPP_14 ++ #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 ++ #define JSON_HAS_CPP_17 ++ #define JSON_HAS_CPP_14 ++ #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) ++ #define JSON_HAS_CPP_14 ++ #endif ++ // the cpp 11 flag is always specified because it is the minimal required version ++ #define JSON_HAS_CPP_11 ++#endif ++ ++#ifdef __has_include ++ #if __has_include() ++ #include ++ #endif ++#endif ++ ++#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) ++ #ifdef JSON_HAS_CPP_17 ++ #if defined(__cpp_lib_filesystem) ++ #define JSON_HAS_FILESYSTEM 1 ++ #elif defined(__cpp_lib_experimental_filesystem) ++ #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 ++ #elif !defined(__has_include) ++ #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 ++ #elif __has_include() ++ #define JSON_HAS_FILESYSTEM 1 ++ #elif __has_include() ++ #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 ++ #endif ++ ++ // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ ++ #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ ++ // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support ++ #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ ++ // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support ++ #if defined(__clang_major__) && __clang_major__ < 7 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ ++ // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support ++ #if defined(_MSC_VER) && _MSC_VER < 1914 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ ++ // no filesystem support before iOS 13 ++ #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ ++ // no filesystem support before macOS Catalina ++ #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 ++ #undef JSON_HAS_FILESYSTEM ++ #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #endif ++ #endif ++#endif ++ ++#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM ++ #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 ++#endif ++ ++#ifndef JSON_HAS_FILESYSTEM ++ #define JSON_HAS_FILESYSTEM 0 ++#endif ++ ++#ifndef JSON_HAS_THREE_WAY_COMPARISON ++ #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ ++ && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L ++ #define JSON_HAS_THREE_WAY_COMPARISON 1 ++ #else ++ #define JSON_HAS_THREE_WAY_COMPARISON 0 ++ #endif ++#endif ++ ++#ifndef JSON_HAS_RANGES ++ // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error ++ #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 ++ #define JSON_HAS_RANGES 0 ++ #elif defined(__cpp_lib_ranges) ++ #define JSON_HAS_RANGES 1 ++ #else ++ #define JSON_HAS_RANGES 0 ++ #endif ++#endif ++ ++#ifdef JSON_HAS_CPP_17 ++ #define JSON_INLINE_VARIABLE inline ++#else ++ #define JSON_INLINE_VARIABLE ++#endif ++ ++#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) ++ #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] ++#else ++ #define JSON_NO_UNIQUE_ADDRESS ++#endif ++ ++// disable documentation warnings on clang ++#if defined(__clang__) ++ #pragma clang diagnostic push ++ #pragma clang diagnostic ignored "-Wdocumentation" ++ #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" ++#endif ++ ++// allow disabling exceptions ++#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) ++ #define JSON_THROW(exception) throw exception ++ #define JSON_TRY try ++ #define JSON_CATCH(exception) catch(exception) ++ #define JSON_INTERNAL_CATCH(exception) catch(exception) ++#else ++ #include ++ #define JSON_THROW(exception) std::abort() ++ #define JSON_TRY if(true) ++ #define JSON_CATCH(exception) if(false) ++ #define JSON_INTERNAL_CATCH(exception) if(false) ++#endif ++ ++// override exception macros ++#if defined(JSON_THROW_USER) ++ #undef JSON_THROW ++ #define JSON_THROW JSON_THROW_USER ++#endif ++#if defined(JSON_TRY_USER) ++ #undef JSON_TRY ++ #define JSON_TRY JSON_TRY_USER ++#endif ++#if defined(JSON_CATCH_USER) ++ #undef JSON_CATCH ++ #define JSON_CATCH JSON_CATCH_USER ++ #undef JSON_INTERNAL_CATCH ++ #define JSON_INTERNAL_CATCH JSON_CATCH_USER ++#endif ++#if defined(JSON_INTERNAL_CATCH_USER) ++ #undef JSON_INTERNAL_CATCH ++ #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER ++#endif ++ ++// allow overriding assert ++#if !defined(JSON_ASSERT) ++ #include // assert ++ #define JSON_ASSERT(x) assert(x) ++#endif ++ ++// allow to access some private functions (needed by the test suite) ++#if defined(JSON_TESTS_PRIVATE) ++ #define JSON_PRIVATE_UNLESS_TESTED public ++#else ++ #define JSON_PRIVATE_UNLESS_TESTED private ++#endif ++ ++/*! ++@brief macro to briefly define a mapping between an enum and JSON ++@def NLOHMANN_JSON_SERIALIZE_ENUM ++@since version 3.4.0 ++*/ ++#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ ++ template \ ++ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ ++ { \ ++ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ ++ static const std::pair m[] = __VA_ARGS__; \ ++ auto it = std::find_if(std::begin(m), std::end(m), \ ++ [e](const std::pair& ej_pair) -> bool \ ++ { \ ++ return ej_pair.first == e; \ ++ }); \ ++ j = ((it != std::end(m)) ? it : std::begin(m))->second; \ ++ } \ ++ template \ ++ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ ++ { \ ++ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ ++ static const std::pair m[] = __VA_ARGS__; \ ++ auto it = std::find_if(std::begin(m), std::end(m), \ ++ [&j](const std::pair& ej_pair) -> bool \ ++ { \ ++ return ej_pair.second == j; \ ++ }); \ ++ e = ((it != std::end(m)) ? it : std::begin(m))->first; \ ++ } ++ ++// Ugly macros to avoid uglier copy-paste when specializing basic_json. They ++// may be removed in the future once the class is split. ++ ++#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ ++ template class ObjectType, \ ++ template class ArrayType, \ ++ class StringType, class BooleanType, class NumberIntegerType, \ ++ class NumberUnsignedType, class NumberFloatType, \ ++ template class AllocatorType, \ ++ template class JSONSerializer, \ ++ class BinaryType> ++ ++#define NLOHMANN_BASIC_JSON_TPL \ ++ basic_json ++ ++// Macros to simplify conversion from/to types ++ ++#define NLOHMANN_JSON_EXPAND( x ) x ++#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME ++#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ ++ NLOHMANN_JSON_PASTE64, \ ++ NLOHMANN_JSON_PASTE63, \ ++ NLOHMANN_JSON_PASTE62, \ ++ NLOHMANN_JSON_PASTE61, \ ++ NLOHMANN_JSON_PASTE60, \ ++ NLOHMANN_JSON_PASTE59, \ ++ NLOHMANN_JSON_PASTE58, \ ++ NLOHMANN_JSON_PASTE57, \ ++ NLOHMANN_JSON_PASTE56, \ ++ NLOHMANN_JSON_PASTE55, \ ++ NLOHMANN_JSON_PASTE54, \ ++ NLOHMANN_JSON_PASTE53, \ ++ NLOHMANN_JSON_PASTE52, \ ++ NLOHMANN_JSON_PASTE51, \ ++ NLOHMANN_JSON_PASTE50, \ ++ NLOHMANN_JSON_PASTE49, \ ++ NLOHMANN_JSON_PASTE48, \ ++ NLOHMANN_JSON_PASTE47, \ ++ NLOHMANN_JSON_PASTE46, \ ++ NLOHMANN_JSON_PASTE45, \ ++ NLOHMANN_JSON_PASTE44, \ ++ NLOHMANN_JSON_PASTE43, \ ++ NLOHMANN_JSON_PASTE42, \ ++ NLOHMANN_JSON_PASTE41, \ ++ NLOHMANN_JSON_PASTE40, \ ++ NLOHMANN_JSON_PASTE39, \ ++ NLOHMANN_JSON_PASTE38, \ ++ NLOHMANN_JSON_PASTE37, \ ++ NLOHMANN_JSON_PASTE36, \ ++ NLOHMANN_JSON_PASTE35, \ ++ NLOHMANN_JSON_PASTE34, \ ++ NLOHMANN_JSON_PASTE33, \ ++ NLOHMANN_JSON_PASTE32, \ ++ NLOHMANN_JSON_PASTE31, \ ++ NLOHMANN_JSON_PASTE30, \ ++ NLOHMANN_JSON_PASTE29, \ ++ NLOHMANN_JSON_PASTE28, \ ++ NLOHMANN_JSON_PASTE27, \ ++ NLOHMANN_JSON_PASTE26, \ ++ NLOHMANN_JSON_PASTE25, \ ++ NLOHMANN_JSON_PASTE24, \ ++ NLOHMANN_JSON_PASTE23, \ ++ NLOHMANN_JSON_PASTE22, \ ++ NLOHMANN_JSON_PASTE21, \ ++ NLOHMANN_JSON_PASTE20, \ ++ NLOHMANN_JSON_PASTE19, \ ++ NLOHMANN_JSON_PASTE18, \ ++ NLOHMANN_JSON_PASTE17, \ ++ NLOHMANN_JSON_PASTE16, \ ++ NLOHMANN_JSON_PASTE15, \ ++ NLOHMANN_JSON_PASTE14, \ ++ NLOHMANN_JSON_PASTE13, \ ++ NLOHMANN_JSON_PASTE12, \ ++ NLOHMANN_JSON_PASTE11, \ ++ NLOHMANN_JSON_PASTE10, \ ++ NLOHMANN_JSON_PASTE9, \ ++ NLOHMANN_JSON_PASTE8, \ ++ NLOHMANN_JSON_PASTE7, \ ++ NLOHMANN_JSON_PASTE6, \ ++ NLOHMANN_JSON_PASTE5, \ ++ NLOHMANN_JSON_PASTE4, \ ++ NLOHMANN_JSON_PASTE3, \ ++ NLOHMANN_JSON_PASTE2, \ ++ NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) ++#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) ++#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) ++#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) ++#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) ++#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) ++#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) ++#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) ++#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) ++#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) ++#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) ++#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) ++#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) ++#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) ++#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) ++#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) ++#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) ++#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) ++#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) ++#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) ++#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) ++#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) ++#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) ++#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) ++#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) ++#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) ++#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) ++#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) ++#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) ++#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) ++#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) ++#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) ++#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) ++#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) ++#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) ++#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) ++#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) ++#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) ++#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) ++#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) ++#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) ++#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) ++#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) ++#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) ++#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) ++#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) ++#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) ++#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) ++#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) ++#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) ++#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) ++#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) ++#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) ++#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) ++#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) ++#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) ++#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) ++#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) ++#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) ++#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) ++#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) ++#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) ++#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) ++#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) ++ ++#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; ++#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); ++#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); ++ ++/*! ++@brief macro ++@def NLOHMANN_DEFINE_TYPE_INTRUSIVE ++@since version 3.9.0 ++*/ ++#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ ++ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ ++ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } ++ ++#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ ++ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ ++ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } ++ ++/*! ++@brief macro ++@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE ++@since version 3.9.0 ++*/ ++#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ ++ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ ++ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } ++ ++#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ ++ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ ++ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } ++ ++ ++// inspired from https://stackoverflow.com/a/26745591 ++// allows to call any std function as if (e.g. with begin): ++// using std::begin; begin(x); ++// ++// it allows using the detected idiom to retrieve the return type ++// of such an expression ++#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ ++ namespace detail { \ ++ using std::std_name; \ ++ \ ++ template \ ++ using result_of_##std_name = decltype(std_name(std::declval()...)); \ ++ } \ ++ \ ++ namespace detail2 { \ ++ struct std_name##_tag \ ++ { \ ++ }; \ ++ \ ++ template \ ++ std_name##_tag std_name(T&&...); \ ++ \ ++ template \ ++ using result_of_##std_name = decltype(std_name(std::declval()...)); \ ++ \ ++ template \ ++ struct would_call_std_##std_name \ ++ { \ ++ static constexpr auto const value = ::nlohmann::detail:: \ ++ is_detected_exact::value; \ ++ }; \ ++ } /* namespace detail2 */ \ ++ \ ++ template \ ++ struct would_call_std_##std_name : detail2::would_call_std_##std_name \ ++ { \ ++ } ++ ++#ifndef JSON_USE_IMPLICIT_CONVERSIONS ++ #define JSON_USE_IMPLICIT_CONVERSIONS 1 ++#endif ++ ++#if JSON_USE_IMPLICIT_CONVERSIONS ++ #define JSON_EXPLICIT ++#else ++ #define JSON_EXPLICIT explicit ++#endif ++ ++#ifndef JSON_DISABLE_ENUM_SERIALIZATION ++ #define JSON_DISABLE_ENUM_SERIALIZATION 0 ++#endif ++ ++#ifndef JSON_USE_GLOBAL_UDLS ++ #define JSON_USE_GLOBAL_UDLS 1 ++#endif ++ ++#if JSON_HAS_THREE_WAY_COMPARISON ++ #include // partial_ordering ++#endif ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++/////////////////////////// ++// JSON type enumeration // ++/////////////////////////// ++ ++/*! ++@brief the JSON type enumeration ++ ++This enumeration collects the different JSON types. It is internally used to ++distinguish the stored values, and the functions @ref basic_json::is_null(), ++@ref basic_json::is_object(), @ref basic_json::is_array(), ++@ref basic_json::is_string(), @ref basic_json::is_boolean(), ++@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), ++@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), ++@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and ++@ref basic_json::is_structured() rely on it. ++ ++@note There are three enumeration entries (number_integer, number_unsigned, and ++number_float), because the library distinguishes these three types for numbers: ++@ref basic_json::number_unsigned_t is used for unsigned integers, ++@ref basic_json::number_integer_t is used for signed integers, and ++@ref basic_json::number_float_t is used for floating-point numbers or to ++approximate integers which do not fit in the limits of their respective type. ++ ++@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON ++value with the default value for a given type ++ ++@since version 1.0.0 ++*/ ++enum class value_t : std::uint8_t ++{ ++ null, ///< null value ++ object, ///< object (unordered set of name/value pairs) ++ array, ///< array (ordered collection of values) ++ string, ///< string value ++ boolean, ///< boolean value ++ number_integer, ///< number value (signed integer) ++ number_unsigned, ///< number value (unsigned integer) ++ number_float, ///< number value (floating-point) ++ binary, ///< binary array (ordered collection of bytes) ++ discarded ///< discarded by the parser callback function ++}; ++ ++/*! ++@brief comparison operator for JSON types ++ ++Returns an ordering that is similar to Python: ++- order: null < boolean < number < object < array < string < binary ++- furthermore, each type is not smaller than itself ++- discarded values are not comparable ++- binary is represented as a b"" string in python and directly comparable to a ++ string; however, making a binary array directly comparable with a string would ++ be surprising behavior in a JSON file. ++ ++@since version 1.0.0 ++*/ ++#if JSON_HAS_THREE_WAY_COMPARISON ++ inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* ++#else ++ inline bool operator<(const value_t lhs, const value_t rhs) noexcept ++#endif ++{ ++ static constexpr std::array order = {{ ++ 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, ++ 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, ++ 6 /* binary */ ++ } ++ }; ++ ++ const auto l_index = static_cast(lhs); ++ const auto r_index = static_cast(rhs); ++#if JSON_HAS_THREE_WAY_COMPARISON ++ if (l_index < order.size() && r_index < order.size()) ++ { ++ return order[l_index] <=> order[r_index]; // *NOPAD* ++ } ++ return std::partial_ordering::unordered; ++#else ++ return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; ++#endif ++} ++ ++// GCC selects the built-in operator< over an operator rewritten from ++// a user-defined spaceship operator ++// Clang, MSVC, and ICC select the rewritten candidate ++// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) ++#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) ++inline bool operator<(const value_t lhs, const value_t rhs) noexcept ++{ ++ return std::is_lt(lhs <=> rhs); // *NOPAD* ++} ++#endif ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++/*! ++@brief replace all occurrences of a substring by another string ++ ++@param[in,out] s the string to manipulate; changed so that all ++ occurrences of @a f are replaced with @a t ++@param[in] f the substring to replace with @a t ++@param[in] t the string to replace @a f ++ ++@pre The search string @a f must not be empty. **This precondition is ++enforced with an assertion.** ++ ++@since version 2.0.0 ++*/ ++template ++inline void replace_substring(StringType& s, const StringType& f, ++ const StringType& t) ++{ ++ JSON_ASSERT(!f.empty()); ++ for (auto pos = s.find(f); // find first occurrence of f ++ pos != StringType::npos; // make sure f was found ++ s.replace(pos, f.size(), t), // replace with t, and ++ pos = s.find(f, pos + t.size())) // find next occurrence of f ++ {} ++} ++ ++/*! ++ * @brief string escaping as described in RFC 6901 (Sect. 4) ++ * @param[in] s string to escape ++ * @return escaped string ++ * ++ * Note the order of escaping "~" to "~0" and "/" to "~1" is important. ++ */ ++template ++inline StringType escape(StringType s) ++{ ++ replace_substring(s, StringType{"~"}, StringType{"~0"}); ++ replace_substring(s, StringType{"/"}, StringType{"~1"}); ++ return s; ++} ++ ++/*! ++ * @brief string unescaping as described in RFC 6901 (Sect. 4) ++ * @param[in] s string to unescape ++ * @return unescaped string ++ * ++ * Note the order of escaping "~1" to "/" and "~0" to "~" is important. ++ */ ++template ++static void unescape(StringType& s) ++{ ++ replace_substring(s, StringType{"~1"}, StringType{"/"}); ++ replace_substring(s, StringType{"~0"}, StringType{"~"}); ++} ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // size_t ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++/// struct to capture the start position of the current token ++struct position_t ++{ ++ /// the total number of characters read ++ std::size_t chars_read_total = 0; ++ /// the number of characters read in the current line ++ std::size_t chars_read_current_line = 0; ++ /// the number of lines read ++ std::size_t lines_read = 0; ++ ++ /// conversion to size_t to preserve SAX interface ++ constexpr operator size_t() const ++ { ++ return chars_read_total; ++ } ++}; ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-FileCopyrightText: 2018 The Abseil Authors ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // array ++#include // size_t ++#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type ++#include // index_sequence, make_index_sequence, index_sequence_for ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++template ++using uncvref_t = typename std::remove_cv::type>::type; ++ ++#ifdef JSON_HAS_CPP_14 ++ ++// the following utilities are natively available in C++14 ++using std::enable_if_t; ++using std::index_sequence; ++using std::make_index_sequence; ++using std::index_sequence_for; ++ ++#else ++ ++// alias templates to reduce boilerplate ++template ++using enable_if_t = typename std::enable_if::type; ++ ++// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h ++// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. ++ ++//// START OF CODE FROM GOOGLE ABSEIL ++ ++// integer_sequence ++// ++// Class template representing a compile-time integer sequence. An instantiation ++// of `integer_sequence` has a sequence of integers encoded in its ++// type through its template arguments (which is a common need when ++// working with C++11 variadic templates). `absl::integer_sequence` is designed ++// to be a drop-in replacement for C++14's `std::integer_sequence`. ++// ++// Example: ++// ++// template< class T, T... Ints > ++// void user_function(integer_sequence); ++// ++// int main() ++// { ++// // user_function's `T` will be deduced to `int` and `Ints...` ++// // will be deduced to `0, 1, 2, 3, 4`. ++// user_function(make_integer_sequence()); ++// } ++template ++struct integer_sequence ++{ ++ using value_type = T; ++ static constexpr std::size_t size() noexcept ++ { ++ return sizeof...(Ints); ++ } ++}; ++ ++// index_sequence ++// ++// A helper template for an `integer_sequence` of `size_t`, ++// `absl::index_sequence` is designed to be a drop-in replacement for C++14's ++// `std::index_sequence`. ++template ++using index_sequence = integer_sequence; ++ ++namespace utility_internal ++{ ++ ++template ++struct Extend; ++ ++// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. ++template ++struct Extend, SeqSize, 0> ++{ ++ using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; ++}; ++ ++template ++struct Extend, SeqSize, 1> ++{ ++ using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; ++}; ++ ++// Recursion helper for 'make_integer_sequence'. ++// 'Gen::type' is an alias for 'integer_sequence'. ++template ++struct Gen ++{ ++ using type = ++ typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; ++}; ++ ++template ++struct Gen ++{ ++ using type = integer_sequence; ++}; ++ ++} // namespace utility_internal ++ ++// Compile-time sequences of integers ++ ++// make_integer_sequence ++// ++// This template alias is equivalent to ++// `integer_sequence`, and is designed to be a drop-in ++// replacement for C++14's `std::make_integer_sequence`. ++template ++using make_integer_sequence = typename utility_internal::Gen::type; ++ ++// make_index_sequence ++// ++// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, ++// and is designed to be a drop-in replacement for C++14's ++// `std::make_index_sequence`. ++template ++using make_index_sequence = make_integer_sequence; ++ ++// index_sequence_for ++// ++// Converts a typename pack into an index sequence of the same length, and ++// is designed to be a drop-in replacement for C++14's ++// `std::index_sequence_for()` ++template ++using index_sequence_for = make_index_sequence; ++ ++//// END OF CODE FROM GOOGLE ABSEIL ++ ++#endif ++ ++// dispatch utility (taken from ranges-v3) ++template struct priority_tag : priority_tag < N - 1 > {}; ++template<> struct priority_tag<0> {}; ++ ++// taken from ranges-v3 ++template ++struct static_const ++{ ++ static JSON_INLINE_VARIABLE constexpr T value{}; ++}; ++ ++#ifndef JSON_HAS_CPP_17 ++ template ++ constexpr T static_const::value; ++#endif ++ ++template ++inline constexpr std::array make_array(Args&& ... args) ++{ ++ return std::array {{static_cast(std::forward(args))...}}; ++} ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // numeric_limits ++#include // false_type, is_constructible, is_integral, is_same, true_type ++#include // declval ++#include // tuple ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++#include // random_access_iterator_tag ++ ++// #include ++ ++// #include ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++namespace detail ++{ ++ ++template ++struct iterator_types {}; ++ ++template ++struct iterator_types < ++ It, ++ void_t> ++{ ++ using difference_type = typename It::difference_type; ++ using value_type = typename It::value_type; ++ using pointer = typename It::pointer; ++ using reference = typename It::reference; ++ using iterator_category = typename It::iterator_category; ++}; ++ ++// This is required as some compilers implement std::iterator_traits in a way that ++// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. ++template ++struct iterator_traits ++{ ++}; ++ ++template ++struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> ++ : iterator_types ++{ ++}; ++ ++template ++struct iterator_traits::value>> ++{ ++ using iterator_category = std::random_access_iterator_tag; ++ using value_type = T; ++ using difference_type = ptrdiff_t; ++ using pointer = T*; ++ using reference = T&; ++}; ++ ++} // namespace detail ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++ ++NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); ++ ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++ ++ ++// #include ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++ ++NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); ++ ++NLOHMANN_JSON_NAMESPACE_END ++ ++// #include ++ ++// #include ++ ++// #include ++// __ _____ _____ _____ ++// __| | __| | | | JSON for Modern C++ ++// | | |__ | | | | | | version 3.11.2 ++// |_____|_____|_____|_|___| https://github.com/nlohmann/json ++// ++// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann ++// SPDX-License-Identifier: MIT ++ ++#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ ++ #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ ++ ++ #include // int64_t, uint64_t ++ #include // map ++ #include // allocator ++ #include // string ++ #include // vector ++ ++ // #include ++ ++ ++ /*! ++ @brief namespace for Niels Lohmann ++ @see https://github.com/nlohmann ++ @since version 1.0.0 ++ */ ++ NLOHMANN_JSON_NAMESPACE_BEGIN ++ ++ /*! ++ @brief default JSONSerializer template argument ++ ++ This serializer ignores the template arguments and uses ADL ++ ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) ++ for serialization. ++ */ ++ template ++ struct adl_serializer; ++ ++ /// a class to store JSON values ++ /// @sa https://json.nlohmann.me/api/basic_json/ ++ template class ObjectType = ++ std::map, ++ template class ArrayType = std::vector, ++ class StringType = std::string, class BooleanType = bool, ++ class NumberIntegerType = std::int64_t, ++ class NumberUnsignedType = std::uint64_t, ++ class NumberFloatType = double, ++ template class AllocatorType = std::allocator, ++ template class JSONSerializer = ++ adl_serializer, ++ class BinaryType = std::vector> ++ class basic_json; ++ ++ /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document ++ /// @sa https://json.nlohmann.me/api/json_pointer/ ++ template ++ class json_pointer; ++ ++ /*! ++ @brief default specialization ++ @sa https://json.nlohmann.me/api/json/ ++ */ ++ using json = basic_json<>; ++ ++ /// @brief a minimal map-like container that preserves insertion order ++ /// @sa https://json.nlohmann.me/api/ordered_map/ ++ template ++ struct ordered_map; ++ ++ /// @brief specialization that maintains the insertion order of object keys ++ /// @sa https://json.nlohmann.me/api/ordered_json/ ++ using ordered_json = basic_json; ++ ++ NLOHMANN_JSON_NAMESPACE_END ++ ++#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ ++ ++ ++NLOHMANN_JSON_NAMESPACE_BEGIN ++/*! ++@brief detail namespace with internal helper functions ++ ++This namespace collects functions that should not be exposed, ++implementations of some @ref basic_json methods, and meta-programming helpers. ++ ++@since version 2.1.0 ++*/ ++namespace detail ++{ ++ ++///////////// ++// helpers // ++///////////// ++ ++// Note to maintainers: ++// ++// Every trait in this file expects a non CV-qualified type. ++// The only exceptions are in the 'aliases for detected' section ++// (i.e. those of the form: decltype(T::member_function(std::declval()))) ++// ++// In this case, T has to be properly CV-qualified to constraint the function arguments ++// (e.g. to_json(BasicJsonType&, const T&)) ++ ++template struct is_basic_json : std::false_type {}; ++ ++NLOHMANN_BASIC_JSON_TPL_DECLARATION ++struct is_basic_json : std::true_type {}; ++ ++// used by exceptions create() member functions ++// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t ++// false_type otherwise ++template ++struct is_basic_json_context : ++ std::integral_constant < bool, ++ is_basic_json::type>::type>::value ++ || std::is_same::value > ++{}; ++ ++////////////////////// ++// json_ref helpers // ++////////////////////// ++ ++template ++class json_ref; ++ ++template ++struct is_json_ref : std::false_type {}; ++ ++template ++struct is_json_ref> : std::true_type {}; ++ ++////////////////////////// ++// aliases for detected // ++////////////////////////// ++ ++template ++using mapped_type_t = typename T::mapped_type; ++ ++template ++using key_type_t = typename T::key_type; ++ ++template ++using value_type_t = typename T::value_type; ++ ++template ++using difference_type_t = typename T::difference_type; ++ ++template ++using pointer_t = typename T::pointer; ++ ++template ++using reference_t = typename T::reference; ++ ++template ++using iterator_category_t = typename T::iterator_category; ++ ++template ++using to_json_function = decltype(T::to_json(std::declval()...)); ++ ++template ++using from_json_function = decltype(T::from_json(std::declval()...)); ++ ++template ++using get_template_function = decltype(std::declval().template get()); ++ ++// trait checking if JSONSerializer::from_json(json const&, udt&) exists ++template ++struct has_from_json : std::false_type {}; ++ ++// trait checking if j.get is valid ++// use this trait instead of std::is_constructible or std::is_convertible, ++// both rely on, or make use of implicit conversions, and thus fail when T ++// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) ++template ++struct is_getable ++{ ++ static constexpr bool value = is_detected::value; ++}; ++ ++template ++struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> ++{ ++ using serializer = typename BasicJsonType::template json_serializer; ++ ++ static constexpr bool value = ++ is_detected_exact::value; ++}; ++ ++// This trait checks if JSONSerializer::from_json(json const&) exists ++// this overload is used for non-default-constructible user-defined-types ++template ++struct has_non_default_from_json : std::false_type {}; ++ ++template ++struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> ++{ ++ using serializer = typename BasicJsonType::template json_serializer; ++ ++ static constexpr bool value = ++ is_detected_exact::value; ++}; ++ ++// This trait checks if BasicJsonType::json_serializer::to_json exists ++// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. ++template ++struct has_to_json : std::false_type {}; ++ ++template ++struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> ++{ ++ using serializer = typename BasicJsonType::template json_serializer; ++ ++ static constexpr bool value = ++ is_detected_exact::value; ++}; ++ ++template ++using detect_key_compare = typename T::key_compare; ++ ++template ++struct has_key_compare : std::integral_constant::value> {}; ++ ++// obtains the actual object key comparator ++template ++struct actual_object_comparator ++{ ++ using object_t = typename BasicJsonType::object_t; ++ using object_comparator_t = typename BasicJsonType::default_object_comparator_t; ++ using type = typename std::conditional < has_key_compare::value, ++ typename object_t::key_compare, object_comparator_t>::type; ++}; ++ ++template ++using actual_object_comparator_t = typename actual_object_comparator::type; ++ ++/////////////////// ++// is_ functions // ++/////////////////// ++ ++// https://en.cppreference.com/w/cpp/types/conjunction ++template struct conjunction : std::true_type { }; ++template struct conjunction : B { }; ++template ++struct conjunction ++: std::conditional(B::value), conjunction, B>::type {}; ++ ++// https://en.cppreference.com/w/cpp/types/negation ++template struct negation : std::integral_constant < bool, !B::value > { }; ++ ++// Reimplementation of is_constructible and is_default_constructible, due to them being broken for ++// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). ++// This causes compile errors in e.g. clang 3.5 or gcc 4.9. ++template ++struct is_default_constructible : std::is_default_constructible {}; ++ ++template ++struct is_default_constructible> ++ : conjunction, is_default_constructible> {}; ++ ++template ++struct is_default_constructible> ++ : conjunction, is_default_constructible> {}; ++ ++template ++struct is_default_constructible> ++ : conjunction...> {}; ++ ++template ++struct is_default_constructible> ++ : conjunction...> {}; ++ ++ ++template ++struct is_constructible : std::is_constructible {}; ++ ++template ++struct is_constructible> : is_default_constructible> {}; ++ ++template ++struct is_constructible> : is_default_constructible> {}; ++ ++template ++struct is_constructible> : is_default_constructible> {}; ++ ++template ++struct is_constructible> : is_default_constructible> {}; ++ ++ ++template ++struct is_iterator_traits : std::false_type {}; ++ ++template ++struct is_iterator_traits> ++{ ++ private: ++ using traits = iterator_traits; ++ ++ public: ++ static constexpr auto value = ++ is_detected::value && ++ is_detected::value && ++ is_detected::value && ++ is_detected::value && ++ is_detected::value; ++}; ++ ++template ++struct is_range ++{ ++ private: ++ using t_ref = typename std::add_lvalue_reference::type; ++ ++ using iterator = detected_t; ++ using sentinel = detected_t; ++ ++ // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator ++ // and https://en.cppreference.com/w/cpp/iterator/sentinel_for ++ // but reimplementing these would be too much work, as a lot of other concepts are used underneath ++ static constexpr auto is_iterator_begin = ++ is_iterator_traits>::value; ++ ++ public: ++ static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; ++}; ++ ++template ++using iterator_t = enable_if_t::value, result_of_begin())>>; ++ ++template ++using range_value_t = value_type_t>>; ++ ++// The following implementation of is_complete_type is taken from ++// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ ++// and is written by Xiang Fan who agreed to using it in this library. ++ ++template ++struct is_complete_type : std::false_type {}; ++ ++template ++struct is_complete_type : std::true_type {}; ++ ++template ++struct is_compatible_object_type_impl : std::false_type {}; ++ ++template ++struct is_compatible_object_type_impl < ++ BasicJsonType, CompatibleObjectType, ++ enable_if_t < is_detected::value&& ++ is_detected::value >> ++{ ++ using object_t = typename BasicJsonType::object_t; ++ ++ // macOS's is_constructible does not play well with nonesuch... ++ static constexpr bool value = ++ is_constructible::value && ++ is_constructible::value; ++}; ++ ++template ++struct is_compatible_object_type ++ : is_compatible_object_type_impl {}; ++ ++template ++struct is_constructible_object_type_impl : std::false_type {}; ++ ++template ++struct is_constructible_object_type_impl < ++ BasicJsonType, ConstructibleObjectType, ++ enable_if_t < is_detected::value&& ++ is_detected::value >> ++{ ++ using object_t = typename BasicJsonType::object_t; ++ ++ static constexpr bool value = ++ (is_default_constructible::value && ++ (std::is_move_assignable::value || ++ std::is_copy_assignable::value) && ++ (is_constructible::value && ++ std::is_same < ++ typename object_t::mapped_type, ++ typename ConstructibleObjectType::mapped_type >::value)) || ++ (has_from_json::value || ++ has_non_default_from_json < ++ BasicJsonType, ++ typename ConstructibleObjectType::mapped_type >::value); ++}; ++ ++template ++struct is_constructible_object_type ++ : is_constructible_object_type_impl {}; ++ ++template ++struct is_compatible_string_type ++{ ++ static constexpr auto value = ++ is_constructible::value; ++}; ++ ++template ++struct is_constructible_string_type ++{ ++ // launder type through decltype() to fix compilation failure on ICPC ++#ifdef __INTEL_COMPILER ++ using laundered_type = decltype(std::declval()); ++#else ++ using laundered_type = ConstructibleStringType; ++#endif ++ ++ static constexpr auto value = ++ conjunction < ++ is_constructible, ++ is_detected_exact>::value; ++}; ++ ++template ++struct is_compatible_array_type_impl : std::false_type {}; ++ ++template ++struct is_compatible_array_type_impl < ++ BasicJsonType, CompatibleArrayType, ++ enable_if_t < ++ is_detected::value&& ++ is_iterator_traits>>::value&& ++// special case for types like std::filesystem::path whose iterator's value_type are themselves ++// c.f. https://github.com/nlohmann/json/pull/3073 ++ !std::is_same>::value >> ++{ ++ static constexpr bool value = ++ is_constructible>::value; ++}; ++ ++template ++struct is_compatible_array_type ++ : is_compatible_array_type_impl {}; ++ ++template ++struct is_constructible_array_type_impl : std::false_type {}; ++ ++template ++struct is_constructible_array_type_impl < ++ BasicJsonType, ConstructibleArrayType, ++ enable_if_t::value >> ++ : std::true_type {}; ++ ++template ++struct is_constructible_array_type_impl < ++ BasicJsonType, ConstructibleArrayType, ++ enable_if_t < !std::is_same::value&& ++ !is_compatible_string_type::value&& ++ is_default_constructible::value&& ++(std::is_move_assignable::value || ++ std::is_copy_assignable::value)&& ++is_detected::value&& ++is_iterator_traits>>::value&& ++is_detected::value&& ++// special case for types like std::filesystem::path whose iterator's value_type are themselves ++// c.f. https://github.com/nlohmann/json/pull/3073 ++!std::is_same>::value&& ++ is_complete_type < ++ detected_t>::value >> ++{ ++ using value_type = range_value_t; ++ ++ static constexpr bool value = ++ std::is_same::value || ++ has_from_json::value || ++ has_non_default_from_json < ++ BasicJsonType, ++ value_type >::value; ++}; ++ ++template ++struct is_constructible_array_type ++ : is_constructible_array_type_impl {}; ++ ++template ++struct is_compatible_integer_type_impl : std::false_type {}; ++ ++template ++struct is_compatible_integer_type_impl < ++ RealIntegerType, CompatibleNumberIntegerType, ++ enable_if_t < std::is_integral::value&& ++ std::is_integral::value&& ++ !std::is_same::value >> ++{ ++ // is there an assert somewhere on overflows? ++ using RealLimits = std::numeric_limits; ++ using CompatibleLimits = std::numeric_limits; ++ ++ static constexpr auto value = ++ is_constructible::value && ++ CompatibleLimits::is_integer && ++ RealLimits::is_signed == CompatibleLimits::is_signed; ++}; ++ ++template ++struct is_compatible_integer_type ++ : is_compatible_integer_type_impl {}; ++ ++template ++struct is_compatible_type_impl: std::false_type {}; ++ ++template ++struct is_compatible_type_impl < ++ BasicJsonType, CompatibleType, ++ enable_if_t::value >> ++{ ++ static constexpr bool value = ++ has_to_json::value; ++}; ++ ++template ++struct is_compatible_type ++ : is_compatible_type_impl {}; ++ ++template ++struct is_constructible_tuple : std::false_type {}; ++ ++template ++struct is_constructible_tuple> : conjunction...> {}; ++ ++template ++struct is_json_iterator_of : std::false_type {}; ++ ++template ++struct is_json_iterator_of : std::true_type {}; ++ ++template ++struct is_json_iterator_of : std::true_type ++{}; ++ ++// checks if a given type T is a template specialization of Primary ++template