Spec-Zone.ru › OCaml 5.0

Модуль Bytes

module Bytes: sig .. end

Операции с последовательностями байтов.

Последовательность байтов — это изменяемая структура данных, которая содержит последовательность байтов фиксированной длины. Каждый байт может быть индексирован за постоянное время для чтения или записи.

Учитывая последовательность байтов s длиной l, мы можем получить доступ к каждому из l байтов s через его индекс в последовательности. Индексы начинаются с 0, и мы будем называть индекс допустимым в s, если он попадает в диапазон [0...l-1] (включительно). Позиция — это точка между двумя байтами или в начале или конце последовательности. Мы называем позицию допустимой в s, если она попадает в диапазон [0...l] (включительно). Обратите внимание, что байт с индексом n находится между позициями n и n+1.

Два параметра start и len считаются определяющими допустимый диапазон s, если len >= 0 и start и start+len являются допустимыми позициями в s.

Последовательности байтов могут быть изменены на месте, например, с помощью функций set и blit, описанных ниже. Смотрите также строки (модуль String), которые являются практически той же структурой данных, но не могут быть изменены на месте.

Байты представлены типом OCaml char.

Метка версия этого модуля может быть использована, как описано в модуле StdLabels.

  • Since 4.02.0
val length : bytes -> int

Возвращает длину (количество байтов) аргумента.

val get : bytes -> int -> char

get s n возвращает байт с индексом n в аргументе s.

  • Raises Invalid_argument если n не является допустимым индексом в s.
val set : bytes -> int -> char -> unit

set s n c изменяет s на месте, заменяя байт с индексом n на c.

  • Raises Invalid_argument если n не является допустимым индексом в s.
val create : int -> bytes

create n возвращает новую последовательность байтов длиной n. Последовательность неинициализирована и содержит произвольные байты.

  • Raises Invalid_argument если n < 0 или n > Sys.max_string_length.
val make : int -> char -> bytes

make n c возвращает новую последовательность байтов длиной n, заполненную байтом c.

  • Raises Invalid_argument если n < 0 или n > Sys.max_string_length.
val init : int -> (int -> char) -> bytes

init n f возвращает новую последовательность байтов длиной n, с символом i инициализированным результатом f i (в порядке возрастания индекса).

  • Raises Invalid_argument если n < 0 или n > Sys.max_string_length.
val empty : bytes

Последовательность байтов размера 0.

val copy : bytes -> bytes

Возвращает новую последовательность байтов, содержащую те же байты, что и аргумент.

val of_string : string -> bytes

Возвращает новую последовательность байтов, содержащую те же байты, что и заданная строка.

val to_string : bytes -> string

Возвращает новую строку, содержащую те же байты, что и заданная последовательность байтов.

val sub : bytes -> int -> int -> bytes

sub s pos len возвращает новую последовательность байтов длиной len, содержащую подпоследовательность s, которая начинается с позиции pos и имеет длину len.

  • Raises Invalid_argument если pos и len не обозначают допустимого диапазона s.
val sub_string : bytes -> int -> int -> string

То же, что и Bytes.sub, но возвращает строку вместо последовательности байтов.

val extend : bytes -> int -> int -> bytes

extend s left right возвращает новую последовательность байтов, содержащую байты s, с left неинициализированными байтами, добавленными в начало и right неинициализированными байтами, добавленными в конец. Если left или right отрицательны, тогда байты удаляются (а не добавляются) с соответствующей стороны s.

  • Since 4.05.0 в BytesLabels
  • Raises Invalid_argument если длина результата отрицательная или больше, чем Sys.max_string_length байтов.
val fill : bytes -> int -> int -> char -> unit

fill s pos len c изменяет s на месте, заменяя len символы на c, начиная с pos.

  • Raises Invalid_argument если pos и len не обозначают допустимого диапазона s.
val blit : bytes -> int -> bytes -> int -> int -> unit

blit src src_pos dst dst_pos len копирует len байтов из последовательности src, начиная с индекса src_pos, в последовательность dst, начиная с индекса dst_pos . Это работает правильно, даже если src и dst — это одна и та же последовательность байтов, а исходный и целевой интервалы перекрываются.

  • Raises Invalid_argument если src_pos и len не обозначают допустимого диапазона src, или если dst_pos и len не обозначают допустимого диапазона dst.
val blit_string : string -> int -> bytes -> int -> int -> unit

blit src src_pos dst dst_pos len копирует len байтов из строки src, начиная с индекса src_pos, в последовательность байтов dst, начиная с индекса dst_pos.

  • Since 4.05.0 в BytesLabels
  • Raises Invalid_argument если src_pos и len не обозначают допустимого диапазона src, или если dst_pos и len не обозначают допустимого диапазона dst.
val concat : bytes -> bytes list -> bytes

concat sep sl конкатенирует список последовательностей байтов sl, вставляя разделительную последовательность байтов sep между каждой, и возвращает результат как новую последовательность байтов.

  • Raises Invalid_argument если результат длиннее, чем Sys.max_string_length байтов.
val cat : bytes -> bytes -> bytes

cat s1 s2 конкатенирует s1 и s2 и возвращает результат как новую последовательность байтов.

  • Since 4.05.0 в BytesLabels
  • Raises Invalid_argument если результат длиннее, чем Sys.max_string_length байтов.
val iter : (char -> unit) -> bytes -> unit

iter f s применяет функцию f по очереди ко всем байтам s . Это эквивалентно f (get s 0); f (get s 1); ...; f (get s
    (length s - 1)); ()
.

val iteri : (int -> char -> unit) -> bytes -> unit

То же, что и Bytes.iter, но функция применяется к индексу байта в качестве первого аргумента и к самому байту как ко второму аргументу.

val map : (char -> char) -> bytes -> bytes

map f s применяет функцию f по очереди ко всем байтам s (в порядке возрастания индекса) и сохраняет полученные байты в новой последовательности, которая возвращается в качестве результата.

val mapi : (int -> char -> char) -> bytes -> bytes

mapi f s вызывает f с каждым символом s и его индексом (в порядке возрастания индекса) и сохраняет полученные байты в новой последовательности, которая возвращается в качестве результата.

val fold_left : ('a -> char -> 'a) -> 'a -> bytes -> 'a

fold_left f x s вычисляет f (... (f (f x (get s 0)) (get s 1)) ...) (get s (n-1)), где n — длина s.

  • Since 4.13.0
val fold_right : (char -> 'a -> 'a) -> bytes -> 'a -> 'a

fold_right f s x вычисляет f (get s 0) (f (get s 1) ( ... (f (get s (n-1)) x) ...)), где n — длина s.

  • Since 4.13.0
val for_all : (char -> bool) -> bytes -> bool

for_all p s проверяет, удовлетворяют ли все символы в s предикату p.

  • Since 4.13.0
val exists : (char -> bool) -> bytes -> bool

exists p s проверяет, удовлетворяет ли хотя бы один символ s предикату p.

  • Since 4.13.0
val trim : bytes -> bytes

Возвращает копию аргумента, без начальных и конечных пробельных символов. Байты, рассматриваемые как пробельные символы, — это ASCII-символы ' ', '\012', '\n', '\r', и '\t'.

val escaped : bytes -> bytes

Возвращает копию аргумента, со специальными символами, представленными последовательностями экранирования, следуя лексическим соглашениям OCaml. Все символы, находящиеся за пределами диапазона ASCII-печатаемых символов (32..126), а также обратный слэш и двойная кавычка экранируются.

  • Возбуждает исключение Invalid_argument если результат длиннее, чем Sys.max_string_length байтов.
val index : bytes -> char -> int

index s c возвращает индекс первого вхождения байта c в s.

  • Возбуждает исключение Not_found если c не встречается в s.
val index_opt : bytes -> char -> int option

index_opt s c возвращает индекс первого вхождения байта c в s или None если c не встречается в s.

  • С версии 4.05
val rindex : bytes -> char -> int

rindex s c возвращает индекс последнего вхождения байта c в s.

  • Возбуждает исключение Not_found если c не встречается в s.
val rindex_opt : bytes -> char -> int option

rindex_opt s c возвращает индекс последнего вхождения байта c в s или None если c не встречается в s.

  • С версии 4.05
val index_from : bytes -> int -> char -> int

index_from s i c возвращает индекс первого вхождения байта c в s после позиции i. index s c эквивалентно index_from s 0 c.

  • Возбуждает исключение
    • Invalid_argument если i не является допустимой позицией в s.
    • Not_found если c не встречается в s после позиции i.
val index_from_opt : bytes -> int -> char -> int option

index_from_opt s i c возвращает индекс первого вхождения байта c в s после позиции i или None если c не встречается в s после позиции i. index_opt s c эквивалентно index_from_opt s 0 c.

  • С версии 4.05
  • Возбуждает исключение Invalid_argument если i не является допустимой позицией в s.
val rindex_from : bytes -> int -> char -> int

rindex_from s i c возвращает индекс последнего вхождения байта c в s перед позицией i+1. rindex s c эквивалентно rindex_from s (length s - 1) c.

  • Возбуждает исключение
    • Invalid_argument если i+1 не является допустимой позицией в s.
    • Not_found если c не встречается в s перед позицией i+1.
val rindex_from_opt : bytes -> int -> char -> int option

rindex_from_opt s i c возвращает индекс последнего вхождения байта c в s перед позицией i+1 или None если c не встречается в s перед позицией i+1. rindex_opt s c эквивалентно rindex_from s (length s - 1) c.

  • С версии 4.05
  • Возбуждает исключение Invalid_argument если i+1 не является допустимой позицией в s.
val contains : bytes -> char -> bool

contains s c проверяет, появляется ли байт c в s.

val contains_from : bytes -> int -> char -> bool

contains_from s start c проверяет, появляется ли байт c в s после позиции start. contains s c эквивалентно contains_from
    s 0 c
.

  • Возбуждает исключение Invalid_argument если start не является допустимой позицией в s.
val rcontains_from : bytes -> int -> char -> bool

rcontains_from s stop c проверяет, появляется ли байт c в s перед позицией stop+1.

  • Возбуждает исключение Invalid_argument если stop < 0 или stop+1 не являются допустимой позицией в s.
val uppercase_ascii : bytes -> bytes

Возвращает копию аргумента, с переводом всех строчных букв в прописные, используя US-ASCII.

  • С версии 4.03.0 (4.05.0 в BytesLabels)
val lowercase_ascii : bytes -> bytes

Возвращает копию аргумента, с переводом всех прописных букв в строчные, используя US-ASCII.

  • С версии 4.03.0 (4.05.0 в BytesLabels)
val capitalize_ascii : bytes -> bytes

Возвращает копию аргумента, с первой буквой в прописной, используя US-ASCII.

  • С версии 4.03.0 (4.05.0 в BytesLabels)
val uncapitalize_ascii : bytes -> bytes

Возвращает копию аргумента, с первой буквой в строчной, используя US-ASCII.

  • С версии 4.03.0 (4.05.0 в BytesLabels)
type t = bytes 

Псевдоним для типа последовательностей байтов.

val compare : t -> t -> int

Функция сравнения последовательностей байтов, с тем же описанием, что и compare. Вместе с типом t, эта функция compare позволяет передать модуль Bytes в качестве аргумента фукнторам Set.Make и Map.Make.

val equal : t -> t -> bool

Функция проверки равенства для последовательностей байтов.

  • С версии 4.03.0 (4.05.0 в BytesLabels)
val starts_with : prefix:bytes -> bytes -> bool

starts_with ~prefix s является true тогда и только тогда, когда s начинается с prefix.

  • С версии 4.13.0
val ends_with : suffix:bytes -> bytes -> bool

ends_with ~suffix s является true тогда и только тогда, когда s заканчивается на suffix.

  • С версии 4.13.0

Небезопасные преобразования (для опытных пользователей)

Этот раздел описывает небезопасные, низкоуровневые функции преобразования между bytes и string. Они не копируют внутренние данные; при неправильном использовании они могут нарушить инвариант неизменяемости строк, предоставляемый опцией -safe-string . Они доступны авторам экспертных библиотек, но для большинства целей вы должны использовать всегда корректные Bytes.to_string и Bytes.of_string вместо них.

val unsafe_to_string : bytes -> string

Небезопасно преобразует последовательность байтов в строку.

Для анализа использования unsafe_to_string, удобно рассмотреть дисциплину «владения». Часть кода, которая манипулирует данными, «владеет» ими; существует несколько разрозненных режимов владения, включая:

  • Уникальное владение: данные могут быть доступны и изменены
  • Общее владение: данные имеют нескольких владельцев, которые могут только получать доступ к ним, но не изменять.

Уникальное владение линейно: передача данных другой части кода означает отказ от владения (мы не можем перезаписать данные). Уникальный владелец может решить сделать данные общими (отказавшись от права изменения), но общие данные не могут снова стать уникальными.

unsafe_to_string s может использоваться только тогда, когда вызывающая сторона владеет последовательностью байтов s — либо уникально, либо как общие неизменяемые данные. Вызывающая сторона отказывается от владения s, и получает владение возвращённой строкой.

Существует два допустимых варианта использования, которые соблюдают эту дисциплину владения:

1. Создание строки путём инициализации и изменения последовательности байтов, которая никогда не меняется после инициализации.

let string_init len f : string =
  let s = Bytes.create len in
  for i = 0 to len - 1 do Bytes.set s i (f i) done;
  Bytes.unsafe_to_string s
   

Эта функция безопасна, потому что последовательность байтов s никогда не будет обработана или изменена после вызова unsafe_to_string. Код string_init отказывается от владения s, и возвращает владение полученной строкой вызывающей стороне.

Обратите внимание, что это было бы небезопасно, если бы s передавался в качестве дополнительного параметра функции f, так как он мог бы таким образом выйти за пределы этой функции и быть изменён в будущем — string_init отказался бы от владения s для передачи его f, и не смог бы безопасно вызвать unsafe_to_string.

Мы предоставили функции String.init, String.map и String.mapi, чтобы охватить большинство случаев построения новых строк. Вы должны отдавать предпочтение этим функциям перед to_string или unsafe_to_string всякий раз, когда это возможно.

2. Временное предоставление владения последовательностью байтов функции, которая ожидает уникально владение строкой и возвращает владение обратно, чтобы мы могли снова изменить последовательность после завершения вызова.

let bytes_length (s : bytes) =
  String.length (Bytes.unsafe_to_string s)
   

В этом случае мы не гарантируем, что s никогда не будет изменён после вызова bytes_length s. Функция String.length временно заимствует уникальное владение последовательностью байтов (и рассматривает её как string), но возвращает это владение обратно вызывающей стороне, которая может предположить, что s по-прежнему является действительной последовательностью байтов после вызова. Обратите внимание, что это верно только потому, что мы знаем, что String.length не захватывает свой аргумент — он может выйти за пределы через побочный канал, такой как комбинатор запоминания.

Вызывающая сторона не может изменить s пока строка заимствована (она временно отказалась от владения). Это влияет на конкурентные программы, а также на функции высшего порядка: если String.length вернула замыкание, которое должно быть вызвано позже, s не должно изменяться до тех пор, пока это замыкание не будет полностью применено и не вернёт владение.

val unsafe_of_string : string -> bytes

Небезопасно преобразует общую строку в последовательность байтов, которую не следует изменять.

Та же дисциплина владения, которая делает unsafe_to_string правильной, применяется к unsafe_of_string: вы можете использовать её, если вы были владельцем значения string, и вы будете владеть возвращаемым значением bytes в том же режиме.

На практике уникальное владение строками чрезвычайно сложно правильно анализировать. Вы всегда должны предполагать, что строки общие, а не уникальные.

Например, строковые литералы неявно являются общими для компилятора, поэтому вы никогда не владеете ими уникально.

let incorrect = Bytes.unsafe_of_string "hello"
let s = Bytes.of_string "hello"
    

Первое объявление неверно, потому что строковый литерал "hello" может быть общим для компилятора с другими частями программы, и изменение incorrect — ошибка. Вы всегда должны использовать вторую версию, которая выполняет копирование и поэтому правильная.

Предположение о уникальном владении строками, которые не являются строковыми литералами, но (частично) построены из строковых литералов, также неверно. Например, изменение unsafe_of_string ("foo" ^ s) может изменить общую строку "foo" — предполагая представление строк в виде верёвки. Более обще, функции, работающие со строками, будут предполагать общее владение, они не сохраняют уникальное владение. Поэтому неверно предполагать уникальное владение результатом unsafe_of_string.

Единственный случай, в котором мы имеем достаточную уверенность в безопасности, заключается в том, что полученная bytes является общей — используется как неизменяемая последовательность байтов. Это может быть полезно для поэтапной миграции программ низкого уровня, которые манипулируют неизменяемыми последовательностями байтов (например, Marshal.from_bytes) и ранее использовали тип string для этой цели.

val split_on_char : char -> bytes -> bytes list

split_on_char sep s возвращает список всех (возможно пустых) подпоследовательностей s, которые ограничены символом sep.

Выход функции определяется следующими инвариантами:

  • Список не пуст.
  • Конкатенация её элементов с использованием sep в качестве разделителя возвращает последовательность байтов, равную входу (Bytes.concat (Bytes.make 1 sep)
          (Bytes.split_on_char sep s) = s
    ).
  • Ни одна последовательность байтов в результате не содержит символ sep.
  • Since 4.13.0

Итераторы

val to_seq : t -> char Seq.t

Итерация по строке в порядке возрастания индексов. Изменения строки во время итерации будут отражены в последовательности.

  • Since 4.07
val to_seqi : t -> (int * char) Seq.t

Итерация по строке в порядке возрастания, возвращая индексы вместе с символами

  • Since 4.07
val of_seq : char Seq.t -> t

Создание строки из генератора

  • Since 4.07

Кодеки и валидации UTF

UTF-8

val get_utf_8_uchar : t -> int -> Uchar.utf_decode

get_utf_8_uchar b i декодирует символ UTF-8 по индексу i в b.

val set_utf_8_uchar : t -> int -> Uchar.t -> int

set_utf_8_uchar b i u кодирует UTF-8 u по индексу i в b и возвращает количество записанных байтов n, начиная с i. Если n равно 0, не хватило места для кодирования u по индексу i, и b осталось нетронутым. В противном случае новый символ может быть закодирован по индексу i + n.

val is_valid_utf_8 : t -> bool

is_valid_utf_8 b равно true, если и только если b содержит валидные данные UTF-8.

UTF-16BE

val get_utf_16be_uchar : t -> int -> Uchar.utf_decode

get_utf_16be_uchar b i декодирует символ UTF-16BE по индексу i в b.

val set_utf_16be_uchar : t -> int -> Uchar.t -> int

set_utf_16be_uchar b i u кодирует UTF-16BE u по индексу i в b и возвращает количество записанных байтов n, начиная с i. Если n равно 0, не хватило места для кодирования u по индексу i, и b осталось нетронутым. В противном случае новый символ может быть закодирован по индексу i + n.

val is_valid_utf_16be : t -> bool

is_valid_utf_16be b равно true, если и только если b содержит валидные данные UTF-16BE.

UTF-16LE

val get_utf_16le_uchar : t -> int -> Uchar.utf_decode

get_utf_16le_uchar b i декодирует символ UTF-16LE по индексу i в b.

val set_utf_16le_uchar : t -> int -> Uchar.t -> int

set_utf_16le_uchar b i u кодирует UTF-16LE u по индексу i в b и возвращает количество записанных байтов n, начиная с i. Если n равно 0, не хватило места для кодирования u по индексу i, и b осталось нетронутым. В противном случае новый символ может быть закодирован по индексу i + n.

val is_valid_utf_16le : t -> bool

is_valid_utf_16le b равно true, если и только если b содержит валидные данные UTF-16LE.

Бинарное кодирование/декодирование целых чисел

Функции в этом разделе бинарно кодируют и декодируют целые числа в последовательности байтов.

Все следующие функции поднимают Invalid_argument если необходимое пространство по индексу i для декодирования или кодирования целого числа недоступно.

Маленький-эндиан (соответственно большой-эндиан) кодирование означает, что наименее (соответственно наиболее) значащие байты хранятся первыми. Большой-эндиан также известен как сетевой порядок байтов. Родной порядок байтов — это либо порядок байтов Little-Endian, либо порядок байтов Big-Endian, в зависимости от Sys.big_endian.

32-битные и 64-битные целые числа представлены типами int32 и int64, которые могут быть интерпретированы как знакомые или беззнаковые числа.

8-битные и 16-битные целые числа представлены типом int, который имеет больше битов, чем бинарное кодирование. Эти дополнительные биты обрабатываются следующим образом:

  • Функции, декодирующие знакомые (соответственно беззнаковые) 8-битные или 16-битные целые числа, представленные значениями int, расширяют свой результат со знаком (соответственно нулём).
  • Функции, кодирующие 8-битные или 16-битные целые числа, представленные значениями int, усекают свой вход до их наименее значимых байтов.
val get_uint8 : bytes -> int -> int

get_uint8 b i — беззнаковое 8-битное целое число b, начиная с байтового индекса i.

  • Since 4.08
val get_int8 : bytes -> int -> int

get_int8 b i — это подписанное 8-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_uint16_ne : bytes -> int -> int

get_uint16_ne b i — это собственный порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_uint16_be : bytes -> int -> int

get_uint16_be b i — это старший порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_uint16_le : bytes -> int -> int

get_uint16_le b i — это младший порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int16_ne : bytes -> int -> int

get_int16_ne b i — это собственный порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int16_be : bytes -> int -> int

get_int16_be b i — это старший порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int16_le : bytes -> int -> int

get_int16_le b i — это младший порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int32_ne : bytes -> int -> int32

get_int32_ne b i — это собственный порядок байтов 32-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int32_be : bytes -> int -> int32

get_int32_be b i — это старший порядок байтов 32-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int32_le : bytes -> int -> int32

get_int32_le b i — это младший порядок байтов 32-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int64_ne : bytes -> int -> int64

get_int64_ne b i — это собственный порядок байтов 64-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int64_be : bytes -> int -> int64

get_int64_be b i — это старший порядок байтов 64-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val get_int64_le : bytes -> int -> int64

get_int64_le b i — это младший порядок байтов 64-битное целое число b, начинающееся с байтового индекса i.

  • Since 4.08
val set_uint8 : bytes -> int -> int -> unit

set_uint8 b i v устанавливает беззнаковое 8-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int8 : bytes -> int -> int -> unit

set_int8 b i v устанавливает подписанное 8-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_uint16_ne : bytes -> int -> int -> unit

set_uint16_ne b i v устанавливает собственный порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_uint16_be : bytes -> int -> int -> unit

set_uint16_be b i v устанавливает старший порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_uint16_le : bytes -> int -> int -> unit

set_uint16_le b i v устанавливает младший порядок байтов беззнаковое 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int16_ne : bytes -> int -> int -> unit

set_int16_ne b i v устанавливает собственный порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int16_be : bytes -> int -> int -> unit

set_int16_be b i v устанавливает старший порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int16_le : bytes -> int -> int -> unit

set_int16_le b i v устанавливает младший порядок байтов со знаком 16-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int32_ne : bytes -> int -> int32 -> unit

set_int32_ne b i v устанавливает собственный порядок байтов 32-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int32_be : bytes -> int -> int32 -> unit

set_int32_be b i v устанавливает старший порядок байтов 32-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int32_le : bytes -> int -> int32 -> unit

set_int32_le b i v устанавливает младший порядок байтов 32-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int64_ne : bytes -> int -> int64 -> unit

set_int64_ne b i v устанавливает собственный порядок байтов 64-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int64_be : bytes -> int -> int64 -> unit

set_int64_be b i v устанавливает старший порядок байтов 64-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08
val set_int64_le : bytes -> int -> int64 -> unit

set_int64_le b i v устанавливает младший порядок байтов 64-битное целое число b, начинающееся с байтового индекса i в значение v.

  • Since 4.08

Последовательности байтов и безопасность потоков

Необходимо быть осторожным при одновременном доступе к последовательностям байтов из нескольких областей: доступ к последовательности байтов никогда не приведет к аварийному завершению программы, но несинхронизированные обращения могут привести к неожиданным (непоследовательным) результатам.

Атомарность

Каждая операция с последовательностью байтов, которая обращается более чем к одному байту, не является атомарной. Это включает итерацию и сканирование.

Например, рассмотрим следующую программу:

let size = 100_000_000
let b = Bytes.make size  ' '
let update b f ()  =
  Bytes.iteri (fun i x -> Bytes.set b i (Char.chr (f (Char.code x)))) b
let d1 = Domain.spawn (update b (fun x -> x + 1))
let d2 = Domain.spawn (update b (fun x -> 2 * x + 1))
let () = Domain.join d1; Domain.join d2

последовательность байтов b может содержать непредсказуемое смешение значений '!', 'A', 'B', и 'C'.

После выполнения этого кода каждый байт последовательности b будет иметь значение '!', 'A', 'B', или 'C'. Если требуется атомарность, пользователь должен реализовать свою собственную синхронизацию (например, используя Mutex.t).

Конфликты данных

Если две области доступа только к непересекающимся частям последовательности байтов, то наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из двух областей.

Конфликт данных возникает, когда две области доступа к одному байту без синхронизации, и по крайней мере одно из обращений является записью. В отсутствии конфликтов данных наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из различных областей.

В случае возможности следует избегать конфликтов данных, используя синхронизацию для управления доступом к элементам последовательности.

Действительно, при наличии конфликтов данных программы не завершатся аварийно, но наблюдаемое поведение может не быть эквивалентно никакому последовательному переплетению операций из различных областей. Тем не менее, даже при наличии конфликтов данных операция чтения вернет значение какой-то предыдущей записи в это место.

Обращения смешанных размеров

Еще один тонкий момент заключается в том, что если конфликт данных включает записи и чтения различных размеров в одно и то же место, порядок, в котором эти записи и чтения наблюдаются областями, не определен. Например, следующий код последовательно записывает 32-битное целое число и char в один и тот же индекс

let b = Bytes.make 10 '\000'
let d1 = Domain.spawn (fun () -> Bytes.set_int32_ne b 0 100; b.[0] <- 'd' )

В этой ситуации область, которая наблюдает запись 'd' в b.0 не гарантирует наблюдение записи в индексы 1, 2, или 3.

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/libref/Bytes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API