package corvus-json-schema
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A fast JSON Schema evaluator (draft 4 to 2020-12) with no dependencies outside the OCaml distribution
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.1.1.tar.gz
sha256=d0a084719770883384e488d42ff1a2c0f84a53e2b2898016183533b8393f2cab
sha512=d5875f234b316cd50a888e1a3acc055133d705eb6622e3856c22f6719fa3eae196f1f08cd08cc073cc0924d27e330ae2ea5388142dd5e91b173bdfd91ad997f0
doc/src/corvus-json-schema.ecmaregex/utf8.ml.html
Source file utf8.ml
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170(* What the Go source takes from the unicode/utf8 package, over a text that is a range of a [Bytes.t] or of a [string]. The Object Pascal port has the same functions in Corvus.JsonSchema.EcmaRegex.Utf8. A decoded character is returned as one [int], the code point above its width in bytes ([(r lsl 3) lor w]), because a pair would be allocated. {!rune} and {!width} take it apart. *) type text = { mutable b : Bytes.t; mutable s : string; mutable is_string : bool } (** The text of a match. Exactly one of [b] and [s] is in use, and [is_string] says which. One record serves both kinds of text, so the matcher is written once and reads a byte through one branch that the processor predicts. *) (** U+FFFD, which a malformed byte of the text decodes to. *) let rune_error = 0xFFFD (** Bytes below this are one character each. *) let rune_self = 0x80 let new_text () = { b = Bytes.empty; s = ""; is_string = true } let byte t i = if t.is_string then Char.code (String.get t.s i) else Char.code (Bytes.get t.b i) let rune packed = packed lsr 3 let width packed = packed land 7 let error1 = (rune_error lsl 3) lor 1 (** [decode t at limit] reads the character at [at] of the text, which ends before [limit]. [at] is below [limit]. Malformed UTF-8 is U+FFFD with a width of one byte, as utf8.DecodeRune of Go reads it: an encoding that is too long, a surrogate and a value beyond U+10FFFF are all malformed. *) let decode t at limit = let p0 = byte t at in if p0 < 0x80 then (p0 lsl 3) lor 1 else if p0 < 0xC2 || p0 > 0xF4 then error1 else let n = limit - at in if p0 < 0xE0 then if n < 2 then error1 else let b1 = byte t (at + 1) in if b1 < 0x80 || b1 > 0xBF then error1 else ((((p0 land 0x1F) lsl 6) lor (b1 land 0x3F)) lsl 3) lor 2 else if p0 < 0xF0 then if n < 3 then error1 else let b1 = byte t (at + 1) in (* E0 must not start an encoding that is too long, and ED must not start a surrogate. *) if (b1 < if p0 = 0xE0 then 0xA0 else 0x80) || b1 > if p0 = 0xED then 0x9F else 0xBF then error1 else let b2 = byte t (at + 2) in if b2 < 0x80 || b2 > 0xBF then error1 else ((((p0 land 0x0F) lsl 12) lor ((b1 land 0x3F) lsl 6) lor (b2 land 0x3F)) lsl 3) lor 3 else if n < 4 then error1 else let b1 = byte t (at + 1) in (* F0 must not start an encoding that is too long, and F4 must not pass U+10FFFF. *) if (b1 < if p0 = 0xF0 then 0x90 else 0x80) || b1 > if p0 = 0xF4 then 0x8F else 0xBF then error1 else let b2 = byte t (at + 2) in if b2 < 0x80 || b2 > 0xBF then error1 else let b3 = byte t (at + 3) in if b3 < 0x80 || b3 > 0xBF then error1 else ((((p0 land 0x07) lsl 18) lor ((b1 land 0x3F) lsl 12) lor ((b2 land 0x3F) lsl 6) lor (b3 land 0x3F)) lsl 3) lor 4 (* The first position at or above [lim], going down from [start], that holds a byte that can start a character. *) let rec rune_start t start lim = if start < lim then lim else if byte t start land 0xC0 <> 0x80 then start else rune_start t (start - 1) lim (** [decode_last t lo limit] reads the character that ends before [limit] in the text that starts at [lo]. [limit] is above [lo]. It is utf8.DecodeLastRune of Go. *) let decode_last t lo limit = let r = byte t (limit - 1) in if r < 0x80 then (r lsl 3) lor 1 else let lim = if limit - 4 > lo then limit - 4 else lo in let start = rune_start t (limit - 2) lim in let packed = decode t start limit in if start + width packed <> limit then error1 else packed (* Matching by UTF-16 code unit over UTF-8 text (units.go of the Go package). ECMA-262 matches a pattern that has no u flag a code unit at a time. The engine reads a pattern without the u flag only when the u flag grammar refuses it, and such a pattern is matched that way. A character of one, two or three bytes of UTF-8 is one code unit. A character of four bytes is two, a high surrogate and a low one, so the matcher has to be able to stand between them. That position is written as the index of the character's third byte. Each half then spans two bytes, every position is still an index into the text, a group is still a pair of indexes, and no UTF-16 copy of the text is made. The third byte of a character is a continuation byte, which is no position at all when matching by code point, so the two readings cannot be confused. Only a text with a character of four bytes differs between the two, and the instructions that compare bytes (a literal run, a word boundary, a line terminator) need no change: none of them can hold at the position between the halves, and all of them are right at every other. *) (** The two UTF-16 code units of a code point beyond the Basic Multilingual Plane. *) let high_surrogate r = 0xD800 + ((r - 0x10000) lsr 10) let low_surrogate r = 0xDC00 + ((r - 0x10000) land 0x3FF) (** [unit_at t lo at hi] reads the code unit at [at] of the text, which is the bytes [lo] up to [hi]. [at] is below [hi]. A half of a character of four bytes has a width of two. *) let unit_at t lo at hi = let c = byte t at in if c >= 0xF0 then let packed = decode t at hi in if width packed = 4 then (high_surrogate (rune packed) lsl 3) lor 2 else error1 else if c >= 0x80 && c < 0xC0 && at - lo >= 2 && byte t (at - 2) >= 0xF0 then (* Between the halves of the character that starts two bytes back. *) let packed = decode t (at - 2) hi in if width packed = 4 then (low_surrogate (rune packed) lsl 3) lor 2 else decode t at hi else decode t at hi (** [unit_before t lo at hi] reads the code unit that ends at [at] of the text, which is the bytes [lo] up to [hi]. [at] is above [lo]. *) let unit_before t lo at hi = let packed = decode_last t lo at in if width packed = 4 then (low_surrogate (rune packed) lsl 3) lor 2 else if packed = error1 && at - lo >= 2 && hi - at >= 2 && byte t (at - 2) >= 0xF0 then (* Between the halves of the character that starts two bytes back. *) let whole = decode t (at - 2) hi in if width whole = 4 then (high_surrogate (rune whole) lsl 3) lor 2 else packed else packed (** Reports whether a code point has an encoding: it is in range and not a surrogate. *) let valid_rune r = (r >= 0 && r < 0xD800) || (r >= 0xE000 && r <= 0x10FFFF) (** The number of bytes of the UTF-8 encoding of a code point that has one. *) let rune_length r = if r < 0x80 then 1 else if r < 0x800 then 2 else if r < 0x10000 then 3 else 4 (** Appends the UTF-8 encoding of a code point. One that has none is written as U+FFFD, as utf8.AppendRune of Go does. *) let add_rune buffer r = let r = if valid_rune r then r else rune_error in let add c = Buffer.add_char buffer (Char.chr c) in if r < 0x80 then add r else if r < 0x800 then begin add (0xC0 lor (r lsr 6)); add (0x80 lor (r land 0x3F)) end else if r < 0x10000 then begin add (0xE0 lor (r lsr 12)); add (0x80 lor ((r lsr 6) land 0x3F)); add (0x80 lor (r land 0x3F)) end else begin add (0xF0 lor (r lsr 18)); add (0x80 lor ((r lsr 12) land 0x3F)); add (0x80 lor ((r lsr 6) land 0x3F)); add (0x80 lor (r land 0x3F)) end (** [runes s units] is the code points of a string, with U+FFFD for each malformed byte. It is the conversion to a slice of runes of Go. With [units] it is the UTF-16 code units of the string: a character beyond the Basic Multilingual Plane is its two surrogates. (Two units are no more elements than the four bytes of the character.) *) let runes s units = let t = { b = Bytes.empty; s; is_string = true } in let n = String.length s in let out = Array.make n 0 in let count = ref 0 and at = ref 0 in while !at < n do let packed = decode t !at n in let r = rune packed in if units && r > 0xFFFF then begin out.(!count) <- high_surrogate r; out.(!count + 1) <- low_surrogate r; count := !count + 2 end else begin out.(!count) <- r; incr count end; at := !at + width packed done; Array.sub out 0 !count
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>