Skip to content

Commit

Permalink
Preparing release 0.1.1.
Browse files Browse the repository at this point in the history
  • Loading branch information
ifazk committed Dec 31, 2021
1 parent f2bfc0d commit 2fc82e8
Show file tree
Hide file tree
Showing 29 changed files with 3,841 additions and 162 deletions.
7 changes: 6 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.1.0 - 2021-12-29
## [0.1.1] - 2021-12-31
### Added
- Support for `int32`, `int64`, and `nativeint`.
- `*.{make_pp_int,make_to_string}` with optional arguments.

## [0.1.0] - 2021-12-29

Initial release.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ The library provides four main functions.
- `Int.pp_int` is a simple `Format` module style pretty printer.
- `Int.pp_binary_int ~flags ~min_width` is a customizable `Format` module style pretty printer.

There are also versions available for `int32`, `int64`, and `nativeint` in the
modules
- `Int32`,
- `Int64`, and
- `Nativeint`.

A generic functor to generate binary-int printers is provided in the `MakePP`
module.

## Basic use

```ocaml
Expand Down
2 changes: 1 addition & 1 deletion dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
(maintainers "Ifaz Kabir")
(source (github ifazk/pp-binary-ints))
(documentation https://ifazk.github.io/pp-binary-ints/)
(version 0.1.0)
(version 0.1.1)

(package
(name pp-binary-ints)
Expand Down
22 changes: 22 additions & 0 deletions lib/Flags.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
type padding =
| Left
| Right (* default *)
| Zeros

type zero_printing =
| OCaml (* depends on padding setting: bunch of zeros (no separators, no prefixs), or space padding on the left or right *)
| InheritNonZero

type flags =
{ padding: padding
; separators: bool
; prefix_non_zero: bool
; zero_printing: zero_printing
}

let default =
{ padding = Right
; separators = false
; prefix_non_zero = false
; zero_printing = OCaml
}
21 changes: 21 additions & 0 deletions lib/Flags.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(** The Flags module contains types to modify how binary integers are
printed. *)

type padding = Left | Right | Zeros
(** [padding] controls whether spaces are are added on the left or right or if
zero prefixes are added. *)

type zero_printing = OCaml | InheritNonZero
(** [zero_printing] controls whether zeros printed similar to how [Printf]
prints zeros or if zeros are printed similar to non-zero integers. *)

type flags = {
padding : padding;
separators : bool;
prefix_non_zero : bool;
zero_printing : zero_printing;
}
(** [flags] are passed to pretty printing functions to customize the output. *)

val default : flags
(** A default set of flags. *)
12 changes: 9 additions & 3 deletions lib/index.mld
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
A library for pretty printing boolean integers.

{1 Library pp-binary-ints}
The entry point of this library is the module:
{!module-Pp_binary_ints.module-Int}.
The entry point of this library is the module: {!module-Pp_binary_ints}.

{1 Examples}

Expand All @@ -16,8 +15,15 @@ The library provides four main functions.
{- {!module-Pp_binary_ints.module-Int.val-pp_binary_int} is a customizable {!module-Format} module style pretty printer which takes in named arguments [~flags] and [~min_width].}
}

The options to customize the outputs can be found in {!module-Pp_binary_ints.Int.Flags}.
The options to customize the outputs can be found in {!module-Pp_binary_ints.Flags}.

We also offer versions of these functions for `int32`, `int64`, `nativeint`, in
the following modules.
{ul
{- {!module-Pp_binary_ints.module-Int32}}
{- {!module-Pp_binary_ints.module-Int64}}
{- {!module-Pp_binary_ints.module-Nativeint}}
}

{2 Basic use}

Expand Down
162 changes: 6 additions & 156 deletions lib/int.ml
Original file line number Diff line number Diff line change
@@ -1,160 +1,10 @@
module Int = Stdlib.Int
module Int: MakePP.S with type t = int = Stdlib.Int

module Flags = struct
type padding =
| Left
| Right (* default *)
| Zeros

type zero_printing =
| OCaml (* depends on padding setting: bunch of zeros (no separators, no prefixs), or space padding on the left or right *)
| InheritNonZero

type flags =
{ padding: padding
; separators: bool
; prefix_non_zero: bool
; zero_printing: zero_printing
}

let default =
{ padding = Right
; separators = false
; prefix_non_zero = false
; zero_printing = OCaml
}
module Dec = struct
let prefix = "0b"
let suffix = ""
end

(* Underscore printing is tricky.
Underscores and prefixes both count towards min width.
Min width 5, no prefix, zero padding.
Ob1111 should be printed as 01111, not _1111
Min width 6, prefix.
Ob1111 should be printed as 0b1111.
Min width 5, with prefix.
0b111 should be printed as 0b111.
*)

(* Utilities *)
let nat_pred n =
if (n > 0) then
n - 1
else
0

let drop_next_bit rev_bits =
rev_bits lsr 1

let get_next_bit_char rev_bits =
if Int.equal 0 (Int.logand 1 rev_bits) then
'0'
else
'1'

(* The next few functions assume zero padding.
For space padding, 1 will be passed as the min_width
If prefix is set to false, then 0 will be passed as the prefix_size.
*)
let not_at_end ~(min_width:int) ~prefix_size rev_bits =
((rev_bits <> 0) || (min_width > prefix_size))

let last_padding ~min_width ~prefix_size rev_bits =
let open Int in
equal rev_bits 0 &&
equal min_width (prefix_size + 1)

let print_underscore ~min_width ~count ~separators ~prefix_size rev_bits =
let open Int in
separators &&
(equal 0 ((count + 1) mod 5)) &&
(not_at_end ~min_width ~prefix_size rev_bits) &&
(not (last_padding ~min_width ~prefix_size rev_bits))

let rec push_chars ~buf ~separators ~prefix_size ~min_width ~count rev_bits : unit =
if print_underscore ~min_width ~count ~separators ~prefix_size rev_bits then
( Buffer.add_char buf '_'
; push_chars ~buf ~separators ~prefix_size ~min_width:(nat_pred min_width) ~count:(count + 1) rev_bits
)
else if (not_at_end ~min_width ~prefix_size rev_bits) then
( Buffer.add_char buf (get_next_bit_char rev_bits)
; let rev_bits = drop_next_bit rev_bits in
let min_width = nat_pred min_width in
let count = count + 1 in
push_chars ~buf ~separators ~prefix_size
~min_width
~count
rev_bits
)
else
()

let rev_buffer ~separators ~prefix ~min_width n : Buffer.t =
let buf = Buffer.create 16 in (* TODO: consider min_width for initial size *)
let prefix_size = (if prefix then 2 else 0) in
( push_chars ~buf ~separators ~prefix_size ~min_width ~count:0 n
; if prefix then
begin
Buffer.add_char buf 'b';
Buffer.add_char buf '0';
end
; buf
)

(* end of assuming zero padding *)

let pp_spaces fmt n =
for _ = 1 to n do
Format.pp_print_char fmt ' ';
done

let pp_rev_buffer fmt buf =
let len = Buffer.length buf in
for i = 1 to len do
Format.pp_print_char fmt (Buffer.nth buf (len - i))
done

let pp_binary_int ~flags ~min_width fmt n =
let open Flags in
let min_width = max 1 min_width in
let {padding; prefix_non_zero; separators; zero_printing} = flags in
let buf =
match padding with
| Left | Right ->
let prefix = prefix_non_zero && ((not (Int.equal 0 n)) || (zero_printing = InheritNonZero)) in
let min_width = if prefix then 3 else 1 in
rev_buffer
~separators
~prefix
~min_width
n
| Zeros ->
if (zero_printing = OCaml) && Int.equal n 0 then
rev_buffer ~separators:false ~prefix:false ~min_width 0
else
let prefix = prefix_non_zero in
let min_width = max min_width (if prefix then 3 else 1) in
rev_buffer ~separators ~prefix ~min_width n
in
let len = Buffer.length buf in
match padding with
| Left ->
begin
pp_spaces fmt (min_width - len);
pp_rev_buffer fmt buf;
end
| Right ->
begin
pp_rev_buffer fmt buf;
pp_spaces fmt (min_width - len);
end
| Zeros ->
pp_rev_buffer fmt buf

let pp_int fmt n =
pp_binary_int ~flags:(Flags.default) ~min_width:1 fmt n

let to_string n : string =
Format.asprintf "%a" pp_int n
module Flags = Flags

let to_string_with ~flags ~min_width : int -> string =
Format.asprintf "%a" (pp_binary_int ~flags ~min_width)
include (MakePP.Make (Int) (Dec))
15 changes: 15 additions & 0 deletions lib/int.mli
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
type t = int

module Flags : sig
(** The Flags module contains types to modify how binary integers are
printed. *)
Expand Down Expand Up @@ -33,6 +35,13 @@ val pp_binary_int :
val pp_int : Format.formatter -> int -> unit
(** [pp_binary_int ~flags ~min_width fmt n] prints the integer [n] on the formatter [fmt]. *)

val make_pp_int :
?flags:Flags.flags -> ?min_width:int -> unit -> Format.formatter -> int -> unit
(** [make_pp_int ?flags ?min_width ()] is just [pp_binary_int ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to pp_binary_int. This version
is nicer to with with the [Format] or [Fmt] modules. *)

val to_string_with : flags:Flags.flags -> min_width:int -> int -> string
(** [to_string_width ~flags ~min_width n] converts the integer [n] to a binary
integer [n]. customizing the output with [~flags]. [~min_width] pads the
Expand All @@ -41,3 +50,9 @@ val to_string_with : flags:Flags.flags -> min_width:int -> int -> string

val to_string : int -> string
(** [to_string n] converts the integer [n] to a binary integer [n]. *)

val make_to_string :
?flags:Flags.flags -> ?min_width:int -> unit -> int -> string
(** [make_to_string ?flags ?min_width ()] is just [to_string_with ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to to_string_with. *)
8 changes: 8 additions & 0 deletions lib/int32.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module I: Internal.S with type t = int32 = Stdlib.Int32

module Dec = struct
let prefix = "0b"
let suffix = "l"
end

include (MakePP.Make (I) (Dec))
33 changes: 33 additions & 0 deletions lib/int32.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
type t = int32

val pp_binary_int :
flags:Flags.flags -> min_width:int -> Format.formatter -> int32 -> unit
(** [pp_binary_int ~flags ~min_width fmt n] prints the integer [n] on the
formatter [fmt], customizing the output with [~flags]. [~min_width] pads the
output with enough spaces or zeros so that the output is at least
[~min_width] characters, depends on [flags.padding]. *)

val pp_int : Format.formatter -> int32 -> unit
(** [pp_binary_int ~flags ~min_width fmt n] prints the integer [n] on the formatter [fmt]. *)

val make_pp_int :
?flags:Flags.flags -> ?min_width:int -> unit -> Format.formatter -> int32 -> unit
(** [make_pp_int ?flags ?min_width ()] is just [pp_binary_int ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to pp_binary_int. This version
is nicer to with with the [Format] or [Fmt] modules. *)

val to_string_with : flags:Flags.flags -> min_width:int -> int32 -> string
(** [to_string_width ~flags ~min_width n] converts the integer [n] to a binary
integer [n]. customizing the output with [~flags]. [~min_width] pads the
output with enough spaces or zeros so that the output is at least
[~min_width] characters, depends on [flags.padding]. *)

val to_string : int32 -> string
(** [to_string n] converts the integer [n] to a binary integer [n]. *)

val make_to_string :
?flags:Flags.flags -> ?min_width:int -> unit -> int32 -> string
(** [make_to_string ?flags ?min_width ()] is just [to_string_with ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to to_string_with. *)
8 changes: 8 additions & 0 deletions lib/int64.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module I: Internal.S with type t = int64 = Stdlib.Int64

module Dec = struct
let prefix = "0b"
let suffix = "L"
end

include (MakePP.Make (I) (Dec))
33 changes: 33 additions & 0 deletions lib/int64.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
type t = int64

val pp_binary_int :
flags:Flags.flags -> min_width:int -> Format.formatter -> int64 -> unit
(** [pp_binary_int ~flags ~min_width fmt n] prints the integer [n] on the
formatter [fmt], customizing the output with [~flags]. [~min_width] pads the
output with enough spaces or zeros so that the output is at least
[~min_width] characters, depends on [flags.padding]. *)

val pp_int : Format.formatter -> int64 -> unit
(** [pp_binary_int ~flags ~min_width fmt n] prints the integer [n] on the formatter [fmt]. *)

val make_pp_int :
?flags:Flags.flags -> ?min_width:int -> unit -> Format.formatter -> int64 -> unit
(** [make_pp_int ?flags ?min_width ()] is just [pp_binary_int ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to pp_binary_int. This version
is nicer to with with the [Format] or [Fmt] modules. *)

val to_string_with : flags:Flags.flags -> min_width:int -> int64 -> string
(** [to_string_width ~flags ~min_width n] converts the integer [n] to a binary
integer [n]. customizing the output with [~flags]. [~min_width] pads the
output with enough spaces or zeros so that the output is at least
[~min_width] characters, depends on [flags.padding]. *)

val to_string : int64 -> string
(** [to_string n] converts the integer [n] to a binary integer [n]. *)

val make_to_string :
?flags:Flags.flags -> ?min_width:int -> unit -> int64 -> string
(** [make_to_string ?flags ?min_width ()] is just [to_string_with ~flags
~min_width], but [flags] and [min_width] are optional. If omitted default
values of [Flags.default] and [1] are passed to to_string_with. *)
Loading

0 comments on commit 2fc82e8

Please sign in to comment.