1234567891011121314151617181920212223242526272829303132333435363738394041424344454647(* Split off to avoid a cyclic dependency with [Or_error]. *)open!Importletinvalid_argf=Printf.invalid_argfletslow_check_pos_len_exn~pos~len~total_length=ifpos<0theninvalid_argf"Negative position: %d"pos();iflen<0theninvalid_argf"Negative length: %d"len();(* We use [pos > total_length - len] rather than [pos + len > total_length] to avoid the
possibility of overflow. *)ifpos>total_length-lentheninvalid_argf"pos + len past end: %d + %d > %d"poslentotal_length()[@@cold][@@inlinenever][@@localnever][@@specialisenever];;letcheck_pos_len_exn~pos~len~total_length=(* This is better than [slow_check_pos_len_exn] for two reasons:
- much less inlined code
- only one conditional jump
The reason it works is that checking [< 0] is testing the highest order bit, so
[a < 0 || b < 0] is the same as [a lor b < 0].
[pos + len] can overflow, so [pos > total_length - len] is not equivalent to
[total_length - len - pos < 0], we need to test for [pos + len] overflow as
well. *)letstop=pos+leninifposlorlenlorstoplor(total_length-stop)<0thenslow_check_pos_len_exn~pos~len~total_length[@@inlinealways];;letget_pos_len_exn?(pos=0)?len()~total_length=letlen=matchlenwith|Somei->i|None->total_length-posincheck_pos_len_exn~pos~len~total_length;pos,len;;modulePrivate=structletslow_check_pos_len_exn=slow_check_pos_len_exnend