extension PureYAML.Parsing.LibYAML { /// Port of libyaml's character-class macros (`IS_*` in `yaml_private.h`). /// libyaml inspects UTF-8 bytes; this operates on `Unicode.Scalar`, where the /// multi-byte line breaks NEL (`U+0085`), LS (`U+2028`), and PS (`U+2029`) are /// single scalars. End of input is `nil`, which is libyaml's `\0` sentinel, so /// `isZ(nil)` is true and every other predicate is false for `nil`. enum CharacterClass { /// `IS_Z`: the end of the input (libyaml's `\0`). static func isZ(_ scalar: Unicode.Scalar?) -> Bool { scalar == nil } /// `IS_SPACE`. static func isSpace(_ scalar: Unicode.Scalar?) -> Bool { scalar == " " } /// `IS_TAB`. static func isTab(_ scalar: Unicode.Scalar?) -> Bool { scalar == "\t" } /// `IS_BLANK`: space or tab. static func isBlank(_ scalar: Unicode.Scalar?) -> Bool { isSpace(scalar) || isTab(scalar) } /// `IS_BREAK`: CR, LF, NEL, LS, or PS. static func isBreak(_ scalar: Unicode.Scalar?) -> Bool { switch scalar { case "\r", "\n", "\u{85}", "\u{2028}", "\u{2029}": true default: false } } /// `IS_BREAKZ`: a line break or the end of input. static func isBreakZ(_ scalar: Unicode.Scalar?) -> Bool { isBreak(scalar) || isZ(scalar) } /// `IS_SPACEZ`: a space, a line break, or the end of input. static func isSpaceZ(_ scalar: Unicode.Scalar?) -> Bool { isSpace(scalar) || isBreakZ(scalar) } /// `IS_BLANKZ`: blank (space or tab), a line break, or the end of input. static func isBlankZ(_ scalar: Unicode.Scalar?) -> Bool { isBlank(scalar) || isBreakZ(scalar) } /// A flow collection indicator (`,`, `[`, `]`, `{`, `}`); the YAML /// `c-flow-indicator` set excluded from `ns-plain-safe` in flow context. static func isFlowIndicator(_ scalar: Unicode.Scalar?) -> Bool { switch scalar { case ",", "[", "]", "{", "}": true default: false } } /// `IS_DIGIT`. static func isDigit(_ scalar: Unicode.Scalar?) -> Bool { guard let scalar else { return false } return scalar >= "0" && scalar <= "9" } /// `IS_ALPHA`: a digit, ASCII letter, `_`, or `-` (the directive, anchor, /// and tag-handle name characters). static func isAlpha(_ scalar: Unicode.Scalar?) -> Bool { guard let scalar else { return false } return (scalar >= "0" && scalar <= "9") || (scalar >= "A" && scalar <= "Z") || (scalar >= "a" && scalar <= "z") || scalar == "_" || scalar == "-" } /// `IS_HEX`: a hexadecimal digit. static func isHex(_ scalar: Unicode.Scalar?) -> Bool { guard let scalar else { return false } return (scalar >= "0" && scalar <= "9") || (scalar >= "A" && scalar <= "F") || (scalar >= "a" && scalar <= "f") } /// `IS_ASCII`. static func isASCII(_ scalar: Unicode.Scalar?) -> Bool { guard let scalar else { return false } return scalar.value <= 0x7F } /// `IS_PRINTABLE`: the YAML `c-printable` set. static func isPrintable(_ scalar: Unicode.Scalar?) -> Bool { guard let scalar else { return false } let value = scalar.value return value == 0x09 || value == 0x0A || value == 0x0D || (value >= 0x20 && value <= 0x7E) || value == 0x85 || (value >= 0xA0 && value <= 0xD7FF) || (value >= 0xE000 && value <= 0xFFFD) || (value >= 0x10000 && value <= 0x10FFFF) } } }