Spec-Zone.ru › OCaml

Модуль 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.

  • С версии 4.02
val length : bytes -> int

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

val get : bytes -> int -> char

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

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

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

  • Вызывает исключение Invalid_argument, если n не является допустимым индексом в s.
val create : int -> bytes

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

  • Вызывает исключение Invalid_argument, если n < 0 или n > Sys.max_string_length.
val make : int -> char -> bytes

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

  • Вызывает исключение Invalid_argument, если n < 0 или n > Sys.max_string_length.
val init : int -> (int -> char) -> bytes

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

  • Вызывает исключение 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.

  • Вызывает исключение 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.

  • С версии 4.05 в BytesLabels
  • Вызывает исключение Invalid_argument, если длина результата отрицательна или превышает Sys.max_string_length байт.
val fill : bytes -> int -> int -> char -> unit

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

  • Вызывает исключение 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 — одна и та же последовательность байтов, а интервалы источника и назначения перекрываются.

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

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

  • С версии 4.05 в BytesLabels
  • Вызывает исключение Invalid_argument, если src_pos и len не задают допустимый диапазон в src или если dst_pos и len не задают допустимый диапазон в dst.
val concat : bytes -> bytes list -> bytes

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

  • Вызывает исключение Invalid_argument, если результат превышает Sys.max_string_length байт.
val cat : bytes -> bytes -> bytes

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

  • С версии 4.05 в BytesLabels
  • Вызывает исключение 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 : ('acc -> char -> 'acc) -> 'acc -> bytes -> 'acc

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

  • С версии 4.13
val fold_right : (char -> 'acc -> 'acc) -> bytes -> 'acc -> 'acc

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

  • С версии 4.13
val for_all : (char -> bool) -> bytes -> bool

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

  • С версии 4.13
val exists : (char -> bool) -> bytes -> bool

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

  • С версии 4.13
val trim : bytes -> bytes

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

val escaped : bytes -> bytes

Возвращает копию аргумента, в которой специальные символы представлены escape-последовательностями в соответствии с лексическими соглашениями 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 (4.05 в BytesLabels)
val lowercase_ascii : bytes -> bytes

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

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

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

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

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

  • С версии 4.03 (4.05 в BytesLabels)
type t = bytes 

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

val compare : t -> t -> int

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

val equal : t -> t -> bool

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

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

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

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

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

  • С версии 4.13

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

В этом разделе описаны небезопасные низкоуровневые функции преобразования между bytes и 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
   

Эта функция безопасна, поскольку после вызова unsafe_to_string последовательность байтов s больше не будет использоваться или изменяться. Код 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. Если s пуст, результатом будет список из одного элемента [empty].

Результат функции определяется следующими инвариантами:

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

Итераторы

val to_seq : t -> char Seq.t

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

  • С версии 4.07
val to_seqi : t -> (int * char) Seq.t

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

  • С версии 4.07
val of_seq : char Seq.t -> t

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

  • С версии 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 кодирует u в формате UTF-8 по индексу 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 кодирует u в формате UTF-16BE по индексу 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 кодирует u в формате UTF-16LE по индексу 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 для декодирования или кодирования целого числа, недоступно.

Кодирование в порядке от младшего к старшему (соответственно, от старшего к младшему) означает, что сначала сохраняются наименее (соответственно, наиболее) значащие байты. Порядок от старшего к младшему также известен как сетевой порядок байтов. Кодирование в нативном порядке байтов выполняется от младшего к старшему или от старшего к младшему в зависимости от 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.

  • Начиная с версии 4.08
val get_int8 : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_uint16_ne : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_uint16_be : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_uint16_le : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_int16_ne : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_int16_be : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_int16_le : bytes -> int -> int

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

  • Начиная с версии 4.08
val get_int32_ne : bytes -> int -> int32

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

  • Начиная с версии 4.08
val get_int32_be : bytes -> int -> int32

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

  • Начиная с версии 4.08
val get_int32_le : bytes -> int -> int32

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

  • Начиная с версии 4.08
val get_int64_ne : bytes -> int -> int64

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

  • Начиная с версии 4.08
val get_int64_be : bytes -> int -> int64

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

  • Начиная с версии 4.08
val get_int64_le : bytes -> int -> int64

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

  • Начиная с версии 4.08
val set_uint8 : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_int8 : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_uint16_ne : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_uint16_be : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_uint16_le : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_int16_ne : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_int16_be : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_int16_le : bytes -> int -> int -> unit

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

  • Начиная с версии 4.08
val set_int32_ne : bytes -> int -> int32 -> unit

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

  • Начиная с версии 4.08
val set_int32_be : bytes -> int -> int32 -> unit

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

  • Начиная с версии 4.08
val set_int32_le : bytes -> int -> int32 -> unit

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

  • Начиная с версии 4.08
val set_int64_ne : bytes -> int -> int64 -> unit

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

  • Начиная с версии 4.08
val set_int64_be : bytes -> int -> int64 -> unit

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

  • Начиная с версии 4.08
val set_int64_le : bytes -> int -> int64 -> unit

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

  • Начиная с версии 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-2026 INRIA.
https://ocaml.org/manual/5.5/api/Bytes.html

Spec-Zone.ru

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