1
0
Fork 0
mirror of https://github.com/tailix/libclayer.git synced 2024-11-13 11:04:17 -05:00

Remove bindings

This commit is contained in:
Alex Kotov 2022-12-25 13:00:20 +04:00
parent 772db061c5
commit 3102a9b57b
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
90 changed files with 0 additions and 5925 deletions

View file

@ -17,88 +17,3 @@ main_freebsd_task:
- sudo make install
main_test_script:
- make check
mruby_freebsd_task:
name: mruby (FreeBSD)
only_if: $CIRRUS_BRANCH == 'master' || $CIRRUS_BASE_BRANCH == 'master'
env:
CPATH: '/usr/local/include'
LIBRARY_PATH: '/usr/local/lib'
MRUBY_YAML_USE_SYSTEM_LIBRARY: x
dependencies_script:
- pkg install --yes autoconf automake git libtool rubygem-rake wget
dependencies_mruby_script:
- wget https://github.com/mruby/mruby/archive/3.1.0.zip -O mruby-3.1.0.zip
- unzip mruby-3.1.0.zip
main_build_script:
- ./autogen.sh
- ./configure CFLAGS='-O3'
- make
- sudo make install
mruby_test_script:
- cd mruby-3.1.0
- MRUBY_CONFIG=../bindings/mruby/build_config.rb rake test
ruby_freebsd_task:
name: Ruby (FreeBSD)
only_if: $CIRRUS_BRANCH == 'master' || $CIRRUS_BASE_BRANCH == 'master'
env:
CPATH: '/usr/local/include'
LIBRARY_PATH: '/usr/local/lib'
dependencies_script:
- pkg install --yes autoconf automake cppcheck git libtool wget
dependencies_ruby_script:
- wget https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.3.tar.gz
- tar -xzf ruby-3.0.3.tar.gz
- cd ruby-3.0.3
- ./configure --disable-install-doc
- make
- sudo make install
main_build_script:
- ./autogen.sh
- ./configure CFLAGS='-O3'
- make
- sudo make install
ruby_build_script:
- cd bindings/ruby
- ./bin/setup
- bundle exec rake compile
ruby_test_script:
- cd bindings/ruby
- bundle exec rake
rust_freebsd_task:
name: Rust (FreeBSD)
only_if: $CIRRUS_BRANCH == 'master' || $CIRRUS_BASE_BRANCH == 'master'
env:
RUSTFLAGS: '-L /usr/local/lib'
dependencies_script:
- pkg install --yes autoconf automake libtool
dependencies_rust_script:
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
main_build_script:
- ./autogen.sh
- ./configure CFLAGS='-O3'
- make
- sudo make install
rust_test_script:
- cd bindings/rust
- ~/.cargo/bin/cargo test
- ~/.cargo/bin/cargo clippy
- ~/.cargo/bin/cargo fmt --check
main_freebsd_port_task:
name: Main (FreeBSD port)
only_if: "changesInclude('.cirrus.yml', 'pkgs/freebsd/**')"
dependencies_script:
- pkg install --yes portfmt portlint porttools
port_prepare_script:
- echo 'DEVELOPER=yes' >> /etc/make.conf
- rm -rf /usr/ports/devel/libkernaux/
- cp -r $CIRRUS_WORKING_DIR/pkgs/freebsd/devel/libkernaux /usr/ports/devel/
port_test_script:
- cd /usr/ports/devel/libkernaux/
- portfmt -D Makefile
- portclippy --strict Makefile
- portlint -A
- port test .

View file

@ -1,48 +0,0 @@
name: mruby
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
env:
MRUBY_YAML_USE_SYSTEM_LIBRARY: x
strategy:
matrix:
assert: ['--disable-assert', '--enable-assert']
packages:
- configure: ''
- configure: '--without-all'
- configure: '--without-all --with-ntoa'
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0
- name: dependencies
run: sudo apt-get --yes install cppcheck libyaml-dev rake
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure ${{matrix.assert}} ${{matrix.packages.configure}} CFLAGS='-O3'
- name: make
run: make
- name: install
run: sudo make install
- name: ldconfig
run: sudo ldconfig
- working-directory: vendor/mruby
name: test
run: MRUBY_CONFIG=../../bindings/mruby/build_config.rb rake test
- working-directory: bindings/mruby
name: setup
run: ./bin/setup
- working-directory: bindings/mruby
name: lint
run: rake

View file

@ -1,46 +0,0 @@
name: Ruby
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
assert: ['--disable-assert', '--enable-assert']
packages:
- configure: ''
- configure: '--without-all'
skip_coverage: 'x'
- configure: '--without-all --with-ntoa'
skip_coverage: 'x'
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0
- name: dependencies
run: sudo apt-get --yes install cppcheck
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure ${{matrix.assert}} ${{matrix.packages.configure}} CFLAGS='-O3'
- name: make
run: make
- name: install
run: sudo make install
- name: ldconfig
run: sudo ldconfig
- working-directory: bindings/ruby
name: setup
run: ./bin/setup
- working-directory: bindings/ruby
name: compile
run: rake compile
- working-directory: bindings/ruby
name: test & lint
run: SKIP_COVERAGE='${{matrix.packages.skip_coverage}}' rake

View file

@ -1,45 +0,0 @@
name: Rust
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
assert: ['--disable-assert', '--enable-assert']
packages:
- configure: ''
- configure: '--without-all'
cargo: '--no-default-features'
- configure: '--without-all --with-ntoa'
cargo: '--no-default-features --features ntoa'
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt, clippy
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure ${{matrix.assert}} ${{matrix.packages.configure}} CFLAGS='-O3'
- name: make
run: make
- name: install
run: sudo make install
- name: ldconfig
run: sudo ldconfig
- working-directory: bindings/rust
name: test
run: cargo test ${{matrix.packages.cargo}}
- working-directory: bindings/rust
name: clippy
run: cargo clippy
- working-directory: bindings/rust
name: fmt
run: cargo fmt --check

View file

@ -162,33 +162,3 @@ if (foo) {
if (foo)
return bar;
```
Python
------
Nothing here yet.
Ruby
----
* Freeze objects if you don't plan to modify them
### Matz's Ruby interpreter
Use **RuboCop**. See [bindings/ruby/.rubocop.yml](/bindings/ruby/.rubocop.yml)
### mruby
Use **RuboCop**. See [bindings/mruby/.rubocop.yml](/bindings/mruby/.rubocop.yml)
Rust
----
Use **rustfmt** and **Clippy**.
See [bindings/rust/rustfmt.toml](/bindings/rust/rustfmt.toml)

View file

@ -1,7 +0,0 @@
/build_config.rb.lock
# For a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in.
/Gemfile.lock
/.ruby-version
/.ruby-gemset

View file

@ -1,81 +0,0 @@
require:
- rubocop-performance
- rubocop-rake
AllCops:
# TODO: Explore which exact syntax version mruby is compatible with
TargetRubyVersion: 2.7
DisplayCopNames: true
NewCops: enable
Layout/AccessModifierIndentation:
EnforcedStyle: outdent
Layout/LineLength:
Max: 80
Lint/AmbiguousOperatorPrecedence:
Enabled: false
Lint/ReturnInVoidContext:
Enabled: false
Metrics/BlockLength:
Exclude:
- 'Rakefile'
- 'test/**/*.rb'
Metrics/BlockNesting:
Exclude:
- 'test/sprintf.rb'
Performance/CollectionLiteralInLoop:
Exclude:
- 'test/**/*.rb'
Security/Eval:
Exclude:
- 'test/**/*.rb'
Security/YAMLLoad:
Exclude:
- 'test/**/*.rb'
Style/AndOr:
EnforcedStyle: conditionals
Style/Documentation:
Exclude:
- 'Rakefile'
Style/DoubleNegation:
Enabled: false
Style/ExpandPathArguments:
# __dir__ is not available in mruby
Enabled: false
Style/FrozenStringLiteralComment:
Enabled: false
Style/HashAsLastArrayItem:
Enabled: false
Style/NumericPredicate:
# Numeric#negative? is not available in mruby
Enabled: false
Style/PerlBackrefs:
Enabled: false
Style/TrailingCommaInArguments:
EnforcedStyleForMultiline: comma
Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: comma
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: comma
Style/VariableInterpolation:
Enabled: false

View file

@ -1,9 +0,0 @@
# frozen_string_literal: true
source 'https://rubygems.org'
gem 'bundler', '~> 2.2'
gem 'rake', '~> 13.0'
gem 'rubocop', '~> 1.25'
gem 'rubocop-performance', '~> 1.13'
gem 'rubocop-rake', '~> 0.6'

View file

@ -1,26 +0,0 @@
::KernAux
=========
[![Build status](https://github.com/tailix/libkernaux/actions/workflows/mruby.yml/badge.svg)](https://github.com/tailix/libkernaux/actions/workflows/mruby.yml)
[![Build status (FreeBSD)](https://api.cirrus-ci.com/github/tailix/libkernaux.svg?task=mruby%20(FreeBSD))](https://cirrus-ci.com/github/tailix/libkernaux)
Binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
library for kernel development.
Install
-------
Add the following to your `build_config.rb`:
```ruby
MRuby::Build.new do |conf|
# ...
conf.gem github: 'tailix/libkernaux',
path: 'bindings/mruby',
branch: 'v0.7.0',
checksum_hash: '1cfff3fca3fc3f8990f43f0d6d5c91929c8f359c'
# ...
end
```

View file

@ -1,29 +0,0 @@
# frozen_string_literal: true
desc 'Run default checks'
task default: :lint
desc 'Run code analysis tools'
task lint: %i[rubocop cppcheck]
desc 'Fix code style (rubocop --auto-correct)'
task fix: 'rubocop:auto_correct'
begin
require 'rubocop/rake_task'
RuboCop::RakeTask.new
rescue LoadError
nil
end
desc 'Run cppcheck'
task :cppcheck do
sh(
'cppcheck',
'--quiet',
'--error-exitcode=1',
'--std=c99',
'--enable=warning,style,performance,portability',
__dir__,
)
end

View file

@ -1,7 +0,0 @@
#!/bin/sh
set -eux
bundle install
# Do any other automated setup that you need to do here

View file

@ -1,6 +0,0 @@
MRuby::Build.new do |conf|
conf.toolchain
conf.enable_test
conf.gem '.'
conf.gem core: 'mruby-bin-mirb'
end

View file

@ -1,21 +0,0 @@
MRuby::Gem::Specification.new 'mruby-kernaux' do |spec|
spec.version = '0.7.0'
spec.license = 'MIT'
spec.homepage =
'https://github.com/tailix/libkernaux/tree/master/bindings/ruby'
spec.author = 'Alex Kotov'
spec.summary =
'Binding to libkernaux - auxiliary library for kernel development'
spec.description = <<~DESCRIPTION.split("\n").map(&:strip).join ' '
Binding to libkernaux - auxiliary library for kernel development.
DESCRIPTION
spec.add_test_dependency 'mruby-eval'
spec.add_test_dependency 'mruby-io'
spec.add_test_dependency 'mruby-random'
spec.add_test_dependency 'mruby-yaml'
spec.linker.libraries << 'kernaux'
end

View file

@ -1,15 +0,0 @@
##
# Binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
# library for kernel development.
#
module KernAux
DEFAULT_ASSERT_CB = @assert_cb = lambda { |file, line, msg|
raise AssertError, "#{file}:#{line}:#{msg}"
}
class Error < RuntimeError; end
class AssertError < Error; end
class CmdlineError < Error; end
class InvalidNtoaBaseError < Error; end
class TooLongNtoaPrefixError < Error; end
end

View file

@ -1,74 +0,0 @@
#include "main.h"
#include <mruby/presym.h>
#include <mruby/string.h>
#include <mruby/variable.h>
static void assert_cb(const char *file, int line, const char *msg);
static mrb_value rb_KernAux_assert_cb(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_assert_cb_EQ(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_assert_do(mrb_state *mrb, mrb_value self);
void init_assert(mrb_state *const mrb)
{
kernaux_assert_cb = assert_cb;
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
mrb_define_class_method(mrb, rb_KernAux, "assert_cb",
rb_KernAux_assert_cb, MRB_ARGS_NONE());
mrb_define_class_method(mrb, rb_KernAux, "assert_cb=",
rb_KernAux_assert_cb_EQ, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "assert_do",
rb_KernAux_assert_do, MRB_ARGS_REQ(3));
}
void assert_cb(const char *const file, const int line, const char *const msg)
{
mrb_state *const mrb = current_mrb_get();
if (!mrb) return;
struct RClass *const self_rbc = mrb_module_get_id(mrb, MRB_SYM(KernAux));
mrb_value self_rb = mrb_obj_value(self_rbc);
mrb_value assert_cb_rb = mrb_iv_get(mrb, self_rb, MRB_IVSYM(assert_cb));
if (mrb_nil_p(assert_cb_rb)) return;
mrb_value file_rb = mrb_str_new_lit(mrb, "");
file_rb = mrb_str_cat_cstr(mrb, file_rb, file);
mrb_value line_rb = mrb_fixnum_value(line);
mrb_value msg_rb = mrb_str_new_lit(mrb, "");
msg_rb = mrb_str_cat_cstr(mrb, msg_rb, msg);
mrb_funcall_id(
mrb, assert_cb_rb, MRB_SYM(call), 3, file_rb, line_rb, msg_rb);
}
mrb_value rb_KernAux_assert_cb(mrb_state *const mrb, const mrb_value self_rb)
{
return mrb_iv_get(mrb, self_rb, MRB_IVSYM(assert_cb));
}
mrb_value rb_KernAux_assert_cb_EQ(mrb_state *const mrb, const mrb_value self_rb)
{
mrb_value assert_cb_rb = mrb_nil_value();
mrb_get_args(mrb, "o", &assert_cb_rb);
mrb_iv_set(mrb, self_rb, MRB_IVSYM(assert_cb), assert_cb_rb);
return assert_cb_rb;
}
mrb_value rb_KernAux_assert_do(mrb_state *const mrb, const mrb_value self_rb)
{
const char *file = NULL;
mrb_int line_rb = 0;
const char *msg = NULL;
mrb_get_args(mrb, "ziz", &file, &line_rb, &msg);
current_mrb_start(mrb);
kernaux_assert_do(file, 0, msg);
current_mrb_finish(mrb);
return mrb_nil_value();
}

View file

@ -1,68 +0,0 @@
#include "main.h"
#include <mruby/array.h>
#include <mruby/presym.h>
#include <mruby/string.h>
#define ARG_COUNT_MAX 256
#define BUFFER_SIZE 4096
#ifdef KERNAUX_VERSION_WITH_CMDLINE
static mrb_value rb_KernAux_cmdline(mrb_state *mrb, mrb_value self);
void init_cmdline(mrb_state *const mrb)
{
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Error =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(Error));
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(CmdlineError),
rb_KernAux_Error);
mrb_define_class_method(mrb, rb_KernAux, "cmdline",
rb_KernAux_cmdline, MRB_ARGS_REQ(1));
}
mrb_value rb_KernAux_cmdline(mrb_state *const mrb, mrb_value self)
{
const char *str;
mrb_get_args(mrb, "z", &str);
size_t argc;
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
char **const argv = malloc(sizeof(char*) * ARG_COUNT_MAX);
char *const buffer = malloc(BUFFER_SIZE);
const bool status = kernaux_cmdline(
str,
error_msg,
&argc,
argv,
buffer,
ARG_COUNT_MAX,
BUFFER_SIZE
);
if (!status) {
free(argv);
free(buffer);
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_CmdlineError =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(CmdlineError));
mrb_raise(mrb, rb_KernAux_CmdlineError, error_msg);
}
mrb_value values[argc];
for (size_t index = 0; index < argc; ++index) {
values[index] = mrb_obj_freeze(
mrb,
mrb_str_cat_cstr(mrb, mrb_str_new_lit(mrb, ""), argv[index])
);
}
free(argv);
free(buffer);
return mrb_obj_freeze(mrb, mrb_ary_new_from_values(mrb, argc, values));
}
#endif // KERNAUX_VERSION_WITH_CMDLINE

View file

@ -1,45 +0,0 @@
#include "dynarg.h"
struct DynArg DynArg_create()
{
struct DynArg dynarg;
DynArg_init(&dynarg);
return dynarg;
}
void DynArg_init(struct DynArg *const dynarg)
{
dynarg->use_dbl = false;
dynarg->dbl = 0.0;
dynarg->arg.str = "";
}
void DynArg_use_char(struct DynArg *const dynarg, const char chr)
{
dynarg->use_dbl = false;
dynarg->arg.chr = chr;
}
void DynArg_use_double(struct DynArg *const dynarg, const double dbl)
{
dynarg->use_dbl = true;
dynarg->dbl = dbl;
}
void DynArg_use_long_long(struct DynArg *const dynarg, const long long ll)
{
dynarg->use_dbl = false;
dynarg->arg.ll = ll;
}
void DynArg_use_str(struct DynArg *const dynarg, const char *const str)
{
dynarg->use_dbl = false;
dynarg->arg.str = str;
}
void DynArg_use_unsigned_long_long(struct DynArg *const dynarg, const unsigned long long ull)
{
dynarg->use_dbl = false;
dynarg->arg.ull = ull;
}

View file

@ -1,42 +0,0 @@
#ifndef INCLUDED_DYNARG
#define INCLUDED_DYNARG
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <kernaux/macro.h>
#include <kernaux/macro/packing_start.run>
struct DynArg {
bool use_dbl;
double dbl;
// TODO: check if this will work on different endianness.
union {
char chr;
long long ll;
const char *str;
unsigned long long ull;
} KERNAUX_PACKED arg;
}
KERNAUX_PACKED;
#include <kernaux/macro/packing_end.run>
struct DynArg DynArg_create();
void DynArg_init(struct DynArg *dynarg);
void DynArg_use_char(struct DynArg *dynarg, char chr);
void DynArg_use_double(struct DynArg *dynarg, double dbl);
void DynArg_use_long_long(struct DynArg *dynarg, long long ll);
void DynArg_use_str(struct DynArg *dynarg, const char *str);
void DynArg_use_unsigned_long_long(struct DynArg *dynarg, unsigned long long ull);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,64 +0,0 @@
#include "main.h"
#include <stddef.h>
#include <mruby/presym.h>
#define MRB_STACK_SIZE 100
// TODO: implement locking
// TODO: replace assertions with actual abort
static size_t mrb_stack_count = 0;
static mrb_state *mrb_stack[MRB_STACK_SIZE];
void mrb_mruby_kernaux_gem_final(mrb_state *const mrb) {}
void mrb_mruby_kernaux_gem_init(mrb_state *const mrb)
{
for (size_t index = mrb_stack_count; index < MRB_STACK_SIZE; ++index) {
mrb_stack[index] = NULL;
}
struct RClass *const rb_KernAux =
mrb_define_module_id(mrb, MRB_SYM(KernAux));
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(Error), E_RUNTIME_ERROR);
init_assert(mrb);
init_version(mrb);
#ifdef KERNAUX_VERSION_WITH_CMDLINE
init_cmdline(mrb);
#endif // KERNAUX_VERSION_WITH_CMDLINE
#ifdef KERNAUX_VERSION_WITH_NTOA
init_ntoa(mrb);
#endif // KERNAUX_VERSION_WITH_NTOA
#ifdef KERNAUX_VERSION_WITH_PRINTF
init_printf(mrb);
#endif // KERNAUX_VERSION_WITH_PRINTF
}
void current_mrb_start(mrb_state *const mrb)
{
mrb_assert(mrb_stack_count < MRB_STACK_SIZE - 1);
mrb_assert(mrb_stack[mrb_stack_count] == NULL);
mrb_assert(mrb != NULL);
mrb_stack[mrb_stack_count++] = mrb;
}
void current_mrb_finish(mrb_state *const mrb)
{
mrb_assert(mrb_stack_count > 0);
mrb_assert(mrb_stack[mrb_stack_count - 1] != NULL);
mrb_assert(mrb_stack[mrb_stack_count - 1] == mrb);
mrb_stack[--mrb_stack_count] = NULL;
}
mrb_state *current_mrb_get()
{
mrb_assert(mrb_stack_count > 0);
mrb_assert(mrb_stack[mrb_stack_count - 1] != NULL);
return mrb_stack[mrb_stack_count - 1];
}

View file

@ -1,30 +0,0 @@
#ifndef __MAIN_H__
#define __MAIN_H__
#include <kernaux.h>
#include <mruby.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void current_mrb_start(mrb_state *mrb);
void current_mrb_finish(mrb_state *mrb);
mrb_state *current_mrb_get();
void init_assert(mrb_state *mrb);
void init_version(mrb_state *mrb);
#ifdef KERNAUX_VERSION_WITH_CMDLINE
void init_cmdline(mrb_state *mrb);
#endif // KERNAUX_VERSION_WITH_CMDLINE
#ifdef KERNAUX_VERSION_WITH_NTOA
void init_ntoa(mrb_state *mrb);
#endif // KERNAUX_VERSION_WITH_NTOA
#ifdef KERNAUX_VERSION_WITH_PRINTF
void init_printf(mrb_state *mrb);
#endif // KERNAUX_VERSION_WITH_PRINTF
#endif

View file

@ -1,298 +0,0 @@
#include "main.h"
#include <mruby/numeric.h>
#include <mruby/presym.h>
#include <mruby/string.h>
#ifdef KERNAUX_VERSION_WITH_NTOA
static mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa2(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa2(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa8(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa8(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa10(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa10(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa16(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa16(mrb_state *mrb, mrb_value self);
static int convert_base(mrb_state *mrb, mrb_value base);
void init_ntoa(mrb_state *const mrb)
{
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Error =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(Error));
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(InvalidNtoaBaseError),
rb_KernAux_Error);
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(TooLongNtoaPrefixError),
rb_KernAux_Error);
mrb_define_class_method(mrb, rb_KernAux, "utoa",
rb_KernAux_utoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa",
rb_KernAux_itoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, rb_KernAux, "utoa2",
rb_KernAux_utoa2, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa2",
rb_KernAux_itoa2, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "utoa8",
rb_KernAux_utoa8, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa8",
rb_KernAux_itoa8, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "utoa10",
rb_KernAux_utoa10, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa10",
rb_KernAux_itoa10, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "utoa16",
rb_KernAux_utoa16, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa16",
rb_KernAux_itoa16, MRB_ARGS_REQ(1));
}
mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_value base;
const char *prefix = NULL;
mrb_int prefix_len = 0;
mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =
mrb_class_get_under_id(
mrb,
rb_KernAux,
MRB_SYM(TooLongNtoaPrefixError)
);
mrb_raisef(mrb, rb_KernAux_TooLongNtoaPrefixError,
"prefix length %d is too long", prefix_len);
}
char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE + prefix_len];
current_mrb_start(mrb);
kernaux_utoa(value, buffer, convert_base(mrb, base), prefix);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_value base;
const char *prefix = NULL;
mrb_int prefix_len = 0;
mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len);
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =
mrb_class_get_under_id(
mrb,
rb_KernAux,
MRB_SYM(TooLongNtoaPrefixError)
);
mrb_raisef(mrb, rb_KernAux_TooLongNtoaPrefixError,
"prefix length %d is too long", prefix_len);
}
char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE + prefix_len];
current_mrb_start(mrb);
kernaux_itoa(value, buffer, convert_base(mrb, base), prefix);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_utoa2(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA2_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_utoa2(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_itoa2(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
char buffer[KERNAUX_ITOA2_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_itoa2(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_utoa8(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA8_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_utoa8(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_itoa8(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
char buffer[KERNAUX_ITOA8_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_itoa8(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_utoa10(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA10_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_utoa10(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_itoa10(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
char buffer[KERNAUX_ITOA10_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_itoa10(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_utoa16(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA16_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_utoa16(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
mrb_value rb_KernAux_itoa16(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_get_args(mrb, "i", &value);
char buffer[KERNAUX_ITOA16_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_itoa16(value, buffer);
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return mrb_obj_freeze(mrb, result);
}
int convert_base(mrb_state *mrb, mrb_value base_rb)
{
if (mrb_obj_is_kind_of(mrb, base_rb, mrb->symbol_class)) {
mrb_sym base_sym = mrb_obj_to_sym(mrb, base_rb);
switch (base_sym) {
case MRB_SYM(b): return 'b';
case MRB_SYM(B): return 'B';
case MRB_SYM(h): return 'h';
case MRB_SYM(H): return 'H';
case MRB_SYM(o): return 'o';
case MRB_SYM(O): return 'O';
case MRB_SYM(d): return 'd';
case MRB_SYM(D): return 'D';
case MRB_SYM(x): return 'x';
case MRB_SYM(X): return 'X';
default:
{
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Error =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(Error));
mrb_raise(mrb, rb_KernAux_Error, "invalid base");
}
}
} else {
return mrb_integer(base_rb);
}
}
#endif // KERNAUX_VERSION_WITH_NTOA

View file

@ -1,144 +0,0 @@
#include "main.h"
#include "dynarg.h"
#include <mruby/array.h>
#include <mruby/error.h>
#include <mruby/presym.h>
#include <mruby/string.h>
#define BUFFER_SIZE 4096
#ifdef KERNAUX_VERSION_WITH_PRINTF
static mrb_value rb_KernAux_sprintf(mrb_state *mrb, mrb_value self);
void init_printf(mrb_state *const mrb)
{
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
mrb_define_class_method(mrb, rb_KernAux, "sprintf", rb_KernAux_sprintf,
MRB_ARGS_REQ(1) | MRB_ARGS_REST());
}
#define TAKE_ARG \
if (arg_index >= argc) { \
mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"); \
} \
mrb_value arg_rb = args[arg_index++]; \
do {} while (0)
mrb_value rb_KernAux_sprintf(mrb_state *const mrb, mrb_value self)
{
const char *format;
mrb_value *args;
mrb_int argc;
mrb_get_args(mrb, "z*", &format, &args, &argc);
int arg_index = 0;
mrb_value result = mrb_str_new_lit(mrb, "");
while (*format) {
if (*format != '%') {
mrb_str_cat(mrb, result, format, 1);
++format;
continue;
}
++format;
struct KernAux_PrintfFmt_Spec spec =
KernAux_PrintfFmt_Spec_create_out(&format);
if (spec.set_width) {
TAKE_ARG;
KernAux_PrintfFmt_Spec_set_width(&spec, mrb_integer(arg_rb));
}
if (spec.set_precision) {
TAKE_ARG;
KernAux_PrintfFmt_Spec_set_precision(&spec, mrb_integer(arg_rb));
}
struct DynArg dynarg = DynArg_create();
if (spec.type == KERNAUX_PRINTF_FMT_TYPE_INT) {
TAKE_ARG;
mrb_ensure_int_type(mrb, arg_rb);
DynArg_use_long_long(&dynarg, mrb_integer(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_UINT) {
TAKE_ARG;
mrb_ensure_int_type(mrb, arg_rb);
DynArg_use_unsigned_long_long(&dynarg, mrb_integer(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_FLOAT ||
spec.type == KERNAUX_PRINTF_FMT_TYPE_EXP)
{
TAKE_ARG;
mrb_ensure_float_type(mrb, arg_rb);
DynArg_use_double(&dynarg, mrb_float(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_CHAR) {
TAKE_ARG;
mrb_ensure_string_type(mrb, arg_rb);
DynArg_use_char(&dynarg, *RSTRING_PTR(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_STR) {
TAKE_ARG;
mrb_ensure_string_type(mrb, arg_rb);
DynArg_use_str(&dynarg, RSTRING_CSTR(mrb, arg_rb));
}
// 1 additional byte for the '%' character.
// 1 additional byte for the terminating '\0' character.
char old_format[2 + spec.format_limit - spec.format_start];
memset(old_format, '\0', sizeof(old_format));
old_format[0] = '%';
strncpy(&old_format[1], spec.format_start, sizeof(old_format) - 2);
char buffer[BUFFER_SIZE];
int slen;
if (spec.set_width) {
if (spec.set_precision) {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, spec.precision,
dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, spec.precision,
dynarg.arg);
}
} else {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, dynarg.arg);
}
}
} else {
if (spec.set_precision) {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.precision, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.precision, dynarg.arg);
}
} else {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.arg);
}
}
}
mrb_str_cat(mrb, result, buffer, slen);
}
if (arg_index < argc) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "too many arguments");
}
return mrb_obj_freeze(mrb, result);
}
#endif // KERNAUX_VERSION_WITH_PRINTF

View file

@ -1,49 +0,0 @@
#include "main.h"
#include <mruby/presym.h>
#include <mruby/value.h>
static mrb_value rb_KernAux_Version_with_cmdlineQN(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_Version_with_ntoaQN(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_Version_with_printfQN(mrb_state *mrb, mrb_value self);
void init_version(mrb_state *const mrb)
{
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Version =
mrb_define_module_under_id(mrb, rb_KernAux, MRB_SYM(Version));
mrb_define_class_method(mrb, rb_KernAux_Version, "with_cmdline?",
rb_KernAux_Version_with_cmdlineQN, MRB_ARGS_REQ(0));
mrb_define_class_method(mrb, rb_KernAux_Version, "with_ntoa?",
rb_KernAux_Version_with_ntoaQN, MRB_ARGS_REQ(0));
mrb_define_class_method(mrb, rb_KernAux_Version, "with_printf?",
rb_KernAux_Version_with_printfQN, MRB_ARGS_REQ(0));
}
mrb_value rb_KernAux_Version_with_cmdlineQN(mrb_state *const mrb, const mrb_value self)
{
#ifdef KERNAUX_VERSION_WITH_CMDLINE
return mrb_true_value();
#else
return mrb_false_value();
#endif
}
mrb_value rb_KernAux_Version_with_ntoaQN(mrb_state *const mrb, const mrb_value self)
{
#ifdef KERNAUX_VERSION_WITH_NTOA
return mrb_true_value();
#else
return mrb_false_value();
#endif
}
mrb_value rb_KernAux_Version_with_printfQN(mrb_state *const mrb, const mrb_value self)
{
#ifdef KERNAUX_VERSION_WITH_PRINTF
return mrb_true_value();
#else
return mrb_false_value();
#endif
}

View file

@ -1,26 +0,0 @@
assert 'KernAux.assert_cb is set by default' do
assert_equal KernAux::DEFAULT_ASSERT_CB, KernAux.assert_cb
end
assert 'we can set KernAux.assert_cb' do
KernAux.assert_cb = nil
assert_equal nil, KernAux.assert_cb
KernAux.assert_cb = 123
assert_equal 123, KernAux.assert_cb
KernAux.assert_cb = KernAux::DEFAULT_ASSERT_CB
assert_equal KernAux::DEFAULT_ASSERT_CB, KernAux.assert_cb
end
assert 'KernAux::DEFAULT_ASSERT_CB raises' do
assert_raise KernAux::AssertError, 'foo.rb:123:bar' do
KernAux::DEFAULT_ASSERT_CB.call 'foo.rb', 123, 'bar'
end
end
assert 'KernAux.assert_do raises' do
assert_raise KernAux::AssertError, 'foo.rb:123:hello' do
KernAux.assert_do 'foo.rb', 123, 'hello'
end
end

View file

@ -1,93 +0,0 @@
def test_cmdline(str, expected)
result = KernAux.cmdline str
assert_true result.instance_of? Array
assert_true result.frozen?
result.each do |item|
assert_true item.instance_of? String
assert_true item.frozen?
end
assert_equal result, expected
end
if KernAux::Version.with_cmdline?
assert 'default' do
test_cmdline 'foo bar\\ baz "car cdr"', ['foo', 'bar baz', 'car cdr']
end
assert 'when str is empty' do
test_cmdline '', []
end
assert 'when str has invalid type' do
assert_raise TypeError, 'Integer cannot be converted to String' do
KernAux.cmdline 123
end
end
assert 'when str has EOL after backslash' do
assert_raise KernAux::CmdlineError, 'EOL after backslash' do
KernAux.cmdline '\\'
end
end
assert 'when str has EOL after backslash inside quote' do
assert_raise KernAux::CmdlineError, 'EOL after backslash inside quote' do
KernAux.cmdline '"\\'
end
end
assert 'when str has unescaped quotation mark' do
assert_raise KernAux::CmdlineError, 'unescaped quotation mark' do
KernAux.cmdline 'foo"'
end
end
assert 'when str has EOL inside quote' do
assert_raise KernAux::CmdlineError, 'EOL inside quote' do
KernAux.cmdline '"'
end
end
assert 'when there are not too many args' do
test_cmdline 'a ' * 256, ['a'] * 256
end
assert 'when there are too many args' do
assert_raise KernAux::CmdlineError, 'too many args' do
KernAux.cmdline 'a ' * 257
end
end
assert 'when args don\'t cause buffer overflow' do
test_cmdline 'a' * 4095, ['a' * 4095]
end
assert 'when args cause buffer overflow' do
assert_raise KernAux::CmdlineError, 'EOF or buffer overflow' do
KernAux.cmdline 'a' * 4096
end
end
assert 'usign fixtures' do
cmdline_yml = File.expand_path('../../../../fixtures/cmdline.yml', __FILE__)
YAML.load(File.read(cmdline_yml)).each do |test|
escape_str = lambda do |str|
eval "\"#{str}\"", nil, __FILE__, __LINE__ # "str"
end
cmdline = escape_str.call test['cmdline']
arg_count_max = test['arg_count_max']
buffer_size = test['buffer_size']
result = test['result']&.map(&escape_str)
next unless arg_count_max.nil? && buffer_size.nil? && !result.nil?
assert "transforms #{cmdline.inspect} to #{result.inspect}" do
assert_equal KernAux.cmdline(cmdline), result
end
end
end
end

View file

@ -1,348 +0,0 @@
def common_assert(expected, result)
assert_true result.instance_of? String
assert_true result.frozen?
assert_equal expected, result
end
def test_utoa(number, base, expected)
common_assert expected, KernAux.utoa(number, base)
common_assert expected, KernAux.utoa(number, base, nil)
common_assert expected, KernAux.utoa(number, base, '')
end
def test_itoa(number, base, expected)
common_assert expected, KernAux.itoa(number, base)
common_assert expected, KernAux.itoa(number, base, nil)
common_assert expected, KernAux.itoa(number, base, '')
end
def test_utoax(number, base, prefix, expected)
common_assert expected, KernAux.utoa(number, base, prefix)
end
def test_itoax(number, base, prefix, expected)
common_assert expected, KernAux.itoa(number, base, prefix)
end
def test_utoa2(number, expected)
common_assert expected, KernAux.utoa2(number)
end
def test_itoa2(number, expected)
common_assert expected, KernAux.itoa2(number)
end
def test_utoa8(number, expected)
common_assert expected, KernAux.utoa8(number)
end
def test_itoa8(number, expected)
common_assert expected, KernAux.itoa8(number)
end
def test_utoa10(number, expected)
common_assert expected, KernAux.utoa10(number)
end
def test_itoa10(number, expected)
common_assert expected, KernAux.itoa10(number)
end
def test_utoa16(number, expected)
common_assert expected, KernAux.utoa16(number)
end
def test_itoa16(number, expected)
common_assert expected, KernAux.itoa16(number)
end
if KernAux::Version.with_ntoa?
assert 'KernAux.utoa' do
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
test_utoa number, base, number.to_s(base)
base = 2 + Random.rand(36 - 2)
test_utoa 0, base, '0'
number = 2**32 - 1
base = 2 + Random.rand(36 - 2)
test_utoa number, base, number.to_s(base)
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
base = 2 + Random.rand(36 - 2)
KernAux.utoa(-1, base)
end
number = Random.rand(2**32 - 1)
base = -(2 + Random.rand(36 - 2))
test_utoa number, base, number.to_s(-base).upcase
number = Random.rand(2**32 - 1)
test_utoa number, :b, number.to_s(2)
number = Random.rand(2**32 - 1)
test_utoa number, :B, number.to_s(2)
number = Random.rand(2**32 - 1)
test_utoa number, :o, number.to_s(8)
number = Random.rand(2**32 - 1)
test_utoa number, :O, number.to_s(8)
number = Random.rand(2**32 - 1)
test_utoa number, :d, number.to_s(10)
number = Random.rand(2**32 - 1)
test_utoa number, :D, number.to_s(10)
number = Random.rand(2**32 - 1)
test_utoa number, :h, number.to_s(16)
number = Random.rand(2**32 - 1)
test_utoa number, :x, number.to_s(16)
number = Random.rand(2**32 - 1)
test_utoa number, :H, number.to_s(16).upcase
number = Random.rand(2**32 - 1)
test_utoa number, :X, number.to_s(16).upcase
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
prefix = 'foo'
test_utoax number, base, prefix, "#{prefix}#{number.abs.to_s(base)}"
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 100
test_utoax number, base, prefix, "#{prefix}#{number.abs.to_s(base)}"
assert_raise(
KernAux::TooLongNtoaPrefixError,
'prefix length 101 is too long',
) do
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 101
KernAux.utoa(number, base, prefix)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**32 - 1).to_s
KernAux.utoa(number.to_s)
end
end
assert 'KernAux.itoa' do
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
test_itoa number, base, number.to_s(base)
base = 2 + Random.rand(36 - 2)
test_itoa 0, base, '0'
base = 2 + Random.rand(36 - 2)
test_itoa 1, base, '1'
base = 2 + Random.rand(36 - 2)
test_itoa(-1, base, '-1')
number = 2**31 - 1
base = 2 + Random.rand(36 - 2)
test_itoa number, base, number.to_s(base)
number = -(2**31 - 1)
base = 2 + Random.rand(36 - 2)
test_itoa number, base, number.to_s(base)
number = 2**31 - 1
base = -(2 + Random.rand(36 - 2))
test_itoa number, base, number.to_s(-base).upcase
number = -(2**31 - 1)
base = -(2 + Random.rand(36 - 2))
test_itoa number, base, number.to_s(-base).upcase
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :b, number.to_s(2)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :B, number.to_s(2)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :o, number.to_s(8)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :O, number.to_s(8)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :d, number.to_s(10)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :D, number.to_s(10)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :h, number.to_s(16)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :x, number.to_s(16)
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :H, number.to_s(16).upcase
number = Random.rand(2**31 - 1) * [1, -1].sample
test_itoa number, :X, number.to_s(16).upcase
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
prefix = 'foo'
sign = number < 0 ? '-' : ''
test_itoax number, base, prefix, "#{sign}#{prefix}#{number.abs.to_s(base)}"
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 100
sign = number < 0 ? '-' : ''
test_itoax number, base, prefix, "#{sign}#{prefix}#{number.abs.to_s(base)}"
assert_raise(
KernAux::TooLongNtoaPrefixError,
'prefix length 101 is too long',
) do
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 101
KernAux.itoa(number, base, prefix)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**31 - 1) * [1, -1].sample
KernAux.itoa(number.to_s)
end
end
assert 'KernAux.utoa2' do
test_utoa2 0, '0b0'
test_utoa2 1, '0b1'
test_utoa2 123, '0b1111011'
test_utoa2 2**32 - 1, "0b#{(2**32 - 1).to_s(2)}"
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
KernAux.utoa2(-1)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**32 - 1).to_s
KernAux.utoa2(number.to_s)
end
end
assert 'KernAux.itoa2' do
test_itoa2 0, '0b0'
test_itoa2 1, '0b1'
test_itoa2(-1, '-0b1')
test_itoa2 123, '0b1111011'
test_itoa2(-123, '-0b1111011')
test_itoa2 2**31 - 1, "0b#{(2**31 - 1).to_s(2)}"
test_itoa2(-2**31, "-0b#{(2**31).to_s(2)}")
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**31 - 1) * [1, -1].sample
KernAux.itoa2(number.to_s)
end
end
assert 'KernAux.utoa8' do
test_utoa8 0, '0o0'
test_utoa8 0o1, '0o1'
test_utoa8 0o123, '0o123'
test_utoa8 2**32 - 1, "0o#{(2**32 - 1).to_s(8)}"
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
KernAux.utoa8(-1)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**32 - 1).to_s
KernAux.utoa8(number.to_s)
end
end
assert 'KernAux.itoa8' do
test_itoa8 0, '0o0'
test_itoa8 0o1, '0o1'
test_itoa8(-0o1, '-0o1')
test_itoa8 0o123, '0o123'
test_itoa8(-0o123, '-0o123')
test_itoa8 2**31 - 1, "0o#{(2**31 - 1).to_s(8)}"
test_itoa8(-2**31, "-0o#{(2**31).to_s(8)}")
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**31 - 1) * [1, -1].sample
KernAux.itoa8(number.to_s)
end
end
assert 'KernAux.utoa10' do
test_utoa10 0, '0'
test_utoa10 1, '1'
test_utoa10 123, '123'
test_utoa10 2**32 - 1, (2**32 - 1).to_s
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
KernAux.utoa10(-1)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**32 - 1).to_s
KernAux.utoa10(number.to_s)
end
end
assert 'KernAux.itoa10' do
test_itoa10 0, '0'
test_itoa10 1, '1'
test_itoa10(-1, '-1')
test_itoa10 123, '123'
test_itoa10(-123, '-123')
test_itoa10 2**31 - 1, (2**31 - 1).to_s
test_itoa10(-2**31, (-2**31).to_s)
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**31 - 1) * [1, -1].sample
KernAux.itoa10(number.to_s)
end
end
assert 'KernAux.utoa16' do
test_utoa16 0, '0x0'
test_utoa16 1, '0x1'
test_utoa16 0x123, '0x123'
test_utoa16 2**32 - 1, "0x#{(2**32 - 1).to_s(16)}"
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
KernAux.utoa16(-1)
end
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**32 - 1).to_s
KernAux.utoa16(number.to_s)
end
end
assert 'KernAux.itoa16' do
test_itoa16 0, '0x0'
test_itoa16 1, '0x1'
test_itoa16(-1, '-0x1')
test_itoa16 0x123, '0x123'
test_itoa16(-0x123, '-0x123')
test_itoa16 2**31 - 1, "0x#{(2**31 - 1).to_s(16)}"
test_itoa16(-2**31, "-0x#{(2**31).to_s(16)}")
assert_raise TypeError, 'no implicit conversion from string' do
number = Random.rand(2**31 - 1) * [1, -1].sample
KernAux.itoa16(number.to_s)
end
end
end

View file

@ -1,113 +0,0 @@
if KernAux::Version.with_printf?
assert 'KernAux.sprintf' do
assert 'integers' do
assert_equal 'i:0', KernAux.sprintf('i:%i', 0)
assert_equal 'u:0', KernAux.sprintf('u:%u', 0)
assert_equal 'i:1', KernAux.sprintf('i:%i', 1)
assert_equal 'u:1', KernAux.sprintf('u:%u', 1)
assert_equal 'i:10', KernAux.sprintf('i:%i', 10)
assert_equal 'u:10', KernAux.sprintf('u:%u', 10)
assert_equal 'i:100', KernAux.sprintf('i:%i', 100)
assert_equal 'u:100', KernAux.sprintf('u:%u', 100)
assert_equal 'i:1000', KernAux.sprintf('i:%i', 1000)
assert_equal 'u:1000', KernAux.sprintf('u:%u', 1000)
assert_equal 'i:10000', KernAux.sprintf('i:%i', 10_000)
assert_equal 'u:10000', KernAux.sprintf('u:%u', 10_000)
assert_equal 'i:100000', KernAux.sprintf('i:%i', 100_000)
assert_equal 'u:100000', KernAux.sprintf('u:%u', 100_000)
assert_equal 'i:1000000', KernAux.sprintf('i:%i', 1_000_000)
assert_equal 'u:1000000', KernAux.sprintf('u:%u', 1_000_000)
assert_equal 'i:10000000', KernAux.sprintf('i:%i', 10_000_000)
assert_equal 'u:10000000', KernAux.sprintf('u:%u', 10_000_000)
assert_equal 'i:100000000', KernAux.sprintf('i:%i', 10**8)
assert_equal 'u:100000000', KernAux.sprintf('u:%u', 10**8)
assert_equal 'i:1000000000', KernAux.sprintf('i:%i', 10**9)
assert_equal 'u:1000000000', KernAux.sprintf('u:%u', 10**9)
assert_equal 'i:2147483647', KernAux.sprintf('i:%i', 2**31 - 1)
assert_equal 'u:2147483647', KernAux.sprintf('u:%u', 2**31 - 1)
end
# TODO: test with different boxing
# assert 'integer overflows' do
# assert_equal 'i:-2147483648', KernAux.sprintf('i:%i', 2**31)
# assert_equal 'u: 2147483648', KernAux.sprintf('u: %u', 2**31)
# assert_equal 'i:-2147483647', KernAux.sprintf('i:%i', 2**31 + 1)
# assert_equal 'u: 2147483649', KernAux.sprintf('u: %u', 2**31 + 1)
# assert_equal 'i:-1', KernAux.sprintf('i:%i', 2**32 - 1)
# assert_equal 'u: 4294967295', KernAux.sprintf('u: %u', 2**32 - 1)
# assert_equal 'i: 0', KernAux.sprintf('i: %i', 2**32)
# assert_equal 'u: 0', KernAux.sprintf('u: %u', 2**32)
# end
assert 'when there are too many arguments' do
[
['Hello!', 'World!'],
['Hello, %s!', 'World', 'Alex'],
].each do |args|
assert_raise ArgumentError, 'too many arguments' do
KernAux.sprintf(*args)
end
end
end
assert 'when there are too few arguments' do
[
[],
['Hello, %s!'],
['Hello, %*s!', 20],
['Hello, %.*s!', 20],
['Hello, %*.*s!', 20, 20],
].each do |args|
assert_raise ArgumentError, 'too few arguments' do
KernAux.sprintf(*args)
end
end
end
[
['', 'using regular fixtures'],
['_orig', 'using original fixtures'],
].each do |(suffix, description)|
assert description do
printf_yml =
File.expand_path("../../../../fixtures/printf#{suffix}.yml", __FILE__)
YAML.load(File.read(printf_yml)).each do |test|
expected = test['result']
format = ''
args = []
test['args'].each do |arg|
if arg.is_a? String
format += arg
else
format += arg[0]
is_int_format = %w[i d u x X o b].any? { |s| arg[0].include? s }
arg[1..].each do |item|
if item.is_a? Array
if item.length == 1
args << item[0]
elsif item[0] == 'long long'
args << item[1]
else
raise "Unknown format: #{args.inspect}"
end
elsif is_int_format && item.is_a?(Float)
args << item.round
else
args << item
end
end
end
end
assert "transforms (#{format.inspect}, #{args.inspect[1...-1]}) " \
"to #{expected.inspect}" do
assert_equal expected, KernAux.sprintf(format, *args)
end
end
end
end
end
end

View file

@ -1,2 +0,0 @@
/dist/
/src/kernaux.egg-info/

View file

@ -1,5 +0,0 @@
kernaux
=======
Binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
library for kernel development.

View file

@ -1,6 +0,0 @@
[build-system]
requires = [
"setuptools>=42",
"wheel"
]
build-backend = "setuptools.build_meta"

View file

@ -1,24 +0,0 @@
[metadata]
name = kernaux
version = 0.0.0
author = Alex Kotov
author_email = kotovalexarian@gmail.com
description = Binding to libkernaux - auxiliary library for kernel development
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/tailix/libkernaux/tree/master/bindings/python
project_urls =
Bug Tracker = https://github.com/tailix/libkernaux/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: POSIX
[options]
package_dir =
= src
packages = find:
python_requires = >=3.8
[options.packages.find]
where = src

View file

@ -1,2 +0,0 @@
def add_one(number):
return number + 1

View file

@ -1,44 +0,0 @@
*.gem
*.rbc
*.so
/.byebug_history
/.config/
/.rake_tasks~
/InstalledFiles/
/pkg/
/tmp/
# Used by dotenv library to load environment variables.
/.env
# RSpec configuration and generated files.
/.rspec
/coverage/
/spec/examples.txt
/spec/reports/
/test/tmp/
/test/version_tmp/
# Documentation cache and generated files.
/.yardoc/
/_yardoc/
/doc/
/rdoc/
# Environment normalization.
/.bundle/
/vendor/bundle/
/lib/bundler/man/
# For a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in.
/Gemfile.lock
/.ruby-version
/.ruby-gemset
# Unless supporting rvm < 1.11.0 or doing something fancy, ignore this.
/.rvmrc
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
/.rubocop-https?--*

View file

@ -1,79 +0,0 @@
require:
- rubocop-performance
- rubocop-rake
- rubocop-rspec
AllCops:
TargetRubyVersion: 3.0
DisplayCopNames: true
NewCops: enable
Layout/AccessModifierIndentation:
EnforcedStyle: outdent
Layout/LineLength:
Max: 80
Lint/AmbiguousOperatorPrecedence:
Enabled: false
Lint/ReturnInVoidContext:
Enabled: false
Metrics/BlockLength:
Exclude:
- '*.gemspec'
- 'Rakefile'
- 'spec/**/*_spec.rb'
RSpec/ContextWording:
Prefixes:
- 'and'
- 'for'
- 'using'
- 'when'
- 'with'
- 'without'
RSpec/FilePath:
CustomTransform:
KernAux: kernaux
RSpec/ExampleLength:
CountAsOne: ['array', 'hash', 'heredoc']
Security/Eval:
Exclude:
- 'spec/**/*_spec.rb'
Style/AndOr:
EnforcedStyle: conditionals
Style/Documentation:
Exclude:
- 'Rakefile'
Style/DoubleNegation:
Enabled: false
Style/GlobalVars:
Exclude:
- 'ext/*/extconf.rb'
Style/HashAsLastArrayItem:
Enabled: false
Style/PerlBackrefs:
Enabled: false
Style/TrailingCommaInArguments:
EnforcedStyleForMultiline: comma
Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: comma
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: comma
Style/VariableInterpolation:
Enabled: false

View file

@ -1,9 +0,0 @@
# frozen_string_literal: true
if ENV['SKIP_COVERAGE'].to_s.empty?
SimpleCov.start do
minimum_coverage 95
add_filter '/spec/'
end
end

View file

@ -1,4 +0,0 @@
--markup markdown
--readme README.md
--protected
--private

View file

@ -1,8 +0,0 @@
# frozen_string_literal: true
source 'https://rubygems.org'
# Specify your gem's dependencies in kernaux.gemspec
gemspec
gem 'simplecov', require: false

View file

@ -1,29 +0,0 @@
::KernAux
=========
[![Build status](https://github.com/tailix/libkernaux/actions/workflows/ruby.yml/badge.svg)](https://github.com/tailix/libkernaux/actions/workflows/ruby.yml)
[![Build status (FreeBSD)](https://api.cirrus-ci.com/github/tailix/libkernaux.svg?task=Ruby%20(FreeBSD))](https://cirrus-ci.com/github/tailix/libkernaux)
Binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
library for kernel development.
Install
-------
Add the following to your `Gemfile`:
```ruby
gem 'kernaux', '~> 0.7.0'
```
Or add the following to your `*.gemspec`:
```ruby
Gem::Specification.new do |spec|
# ...
spec.add_runtime_dependency 'kernaux', '~> 0.7.0'
# ...
end
```

View file

@ -1,92 +0,0 @@
# frozen_string_literal: true
require 'bundler/gem_tasks'
module Bundler
class GemHelper
def tag_version(*)
yield if block_given?
end
def git_push(*); end
def perform_git_push(*); end
end
end
CLEAN << '.yardoc'
CLEAN << 'coverage'
CLEAN << 'doc'
CLEAN << 'spec/examples.txt'
desc 'Run default checks'
task default: %i[test lint]
desc 'Run tests'
task test: :spec
desc 'Run code analysis tools'
task lint: %i[rubocop cppcheck yard:cov]
desc 'Fix code style (rubocop --auto-correct)'
task fix: 'rubocop:auto_correct'
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new
rescue LoadError
nil
end
begin
require 'rubocop/rake_task'
RuboCop::RakeTask.new
rescue LoadError
nil
end
begin
require 'yard'
YARD::Rake::YardocTask.new
rescue LoadError
nil
end
begin
require 'rake/extensiontask'
Rake::ExtensionTask.new 'default' do |ext|
ext.lib_dir = 'lib/kernaux'
end
rescue LoadError
nil
end
desc 'Open development console'
task :console do
sh 'bundle', 'exec', File.expand_path(File.join('bin', 'console'), __dir__)
end
desc 'Run cppcheck'
task :cppcheck do
sh(
'cppcheck',
'--quiet',
'--error-exitcode=1',
'--std=c99',
'--enable=warning,style,performance,portability',
__dir__,
)
end
namespace :yard do
desc 'Measure documentation coverage'
task :cov do
result = `bundle exec yard stats`.lines.last.strip.freeze
m = result.match(/\A(\d+(\.\d+)?)% documented\z/)
raise 'Invalid result' if m.nil?
coverage = m[1].to_f.round(2)
puts "Documentation coverage: #{coverage}%"
raise 'Not fully documented!' if coverage != 100
end
end

View file

@ -1,8 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'kernaux'
require 'pry'
Pry.start

View file

@ -1,7 +0,0 @@
#!/bin/sh
set -eux
bundle install
# Do any other automated setup that you need to do here

View file

@ -1,55 +0,0 @@
#include "main.h"
static void assert_cb(const char *file, int line, const char *msg);
static VALUE rb_KernAux_assert_cb(VALUE self);
static VALUE rb_KernAux_assert_cb_EQ(VALUE self, VALUE assert_cb);
static
VALUE rb_KernAux_assert_do(VALUE self, VALUE file, VALUE line, VALUE msg);
void init_assert()
{
kernaux_assert_cb = assert_cb;
rb_define_singleton_method(rb_KernAux, "assert_cb",
rb_KernAux_assert_cb, 0);
rb_define_singleton_method(rb_KernAux, "assert_cb=",
rb_KernAux_assert_cb_EQ, 1);
rb_define_singleton_method(rb_KernAux, "assert_do",
rb_KernAux_assert_do, 3);
}
void assert_cb(const char *const file, const int line, const char *const msg)
{
const VALUE assert_cb_rb = rb_iv_get(rb_KernAux, "@assert_cb");
if (assert_cb_rb == Qnil) return;
const VALUE file_rb = rb_str_new2(file);
const VALUE line_rb = INT2FIX(line);
const VALUE msg_rb = rb_str_new2(msg);
rb_funcall(assert_cb_rb, rb_intern_call, 3, file_rb, line_rb, msg_rb);
}
VALUE rb_KernAux_assert_cb(const VALUE self)
{
return rb_iv_get(self, "@assert_cb");
}
VALUE rb_KernAux_assert_cb_EQ(const VALUE self, const VALUE assert_cb_rb)
{
return rb_iv_set(self, "@assert_cb", assert_cb_rb);
}
VALUE rb_KernAux_assert_do(
const VALUE self_rb KERNAUX_UNUSED,
VALUE file_rb,
const VALUE line_rb,
VALUE msg_rb
) {
const char *const file = StringValueCStr(file_rb);
const int line = FIX2INT(line_rb);
const char *const msg = StringValueCStr(msg_rb);
kernaux_assert_do(file, line, msg);
return Qnil;
}

View file

@ -1,83 +0,0 @@
#include "main.h"
#ifdef KERNAUX_VERSION_WITH_CMDLINE
#define ARG_COUNT_MAX 256
#define BUFFER_SIZE 4096
struct Data {
char error_msg[KERNAUX_CMDLINE_ERROR_MSG_SIZE_MAX];
char *argv[ARG_COUNT_MAX];
char buffer[BUFFER_SIZE];
};
static VALUE rb_ANON_Data_ALLOC(VALUE klass);
static VALUE rb_KernAux_cmdline(VALUE self, VALUE cmdline);
static const struct rb_data_type_struct info = {
.wrap_struct_name = "cmdline",
.function = {
.dmark = NULL,
.dfree = RUBY_DEFAULT_FREE,
.dsize = NULL,
.dcompact = NULL,
.reserved = { 0 },
},
.parent = NULL,
.data = NULL,
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
};
static VALUE rb_KernAux_CmdlineError = Qnil;
static VALUE rb_ANON_Data = Qnil;
void init_cmdline()
{
rb_gc_register_mark_object(rb_KernAux_CmdlineError =
rb_define_class_under(rb_KernAux, "CmdlineError", rb_KernAux_Error));
rb_gc_register_mark_object(rb_ANON_Data =
rb_funcall(rb_cClass, rb_intern_new, 1, rb_cObject));
rb_define_alloc_func(rb_ANON_Data, rb_ANON_Data_ALLOC);
rb_define_singleton_method(rb_KernAux, "cmdline", rb_KernAux_cmdline, 1);
}
VALUE rb_ANON_Data_ALLOC(const VALUE klass)
{
struct Data *data;
return TypedData_Make_Struct(klass, struct Data, &info, data);
}
VALUE rb_KernAux_cmdline(const VALUE self_rb, VALUE cmdline_rb)
{
const char *const cmdline = StringValueCStr(cmdline_rb);
size_t argc;
const VALUE data_rb = rb_funcall(rb_ANON_Data, rb_intern_new, 0);
struct Data *data;
TypedData_Get_Struct(data_rb, struct Data, &info, data);
if (!data) rb_raise(rb_KernAux_CmdlineError, "internal error");
const bool result = kernaux_cmdline(
cmdline,
data->error_msg,
&argc,
data->argv,
data->buffer,
ARG_COUNT_MAX,
BUFFER_SIZE
);
if (!result) rb_raise(rb_KernAux_CmdlineError, "%s", data->error_msg);
VALUE result_rb = rb_ary_new2(argc);
for (size_t index = 0; index < argc; ++index) {
rb_ary_push(
result_rb,
rb_funcall(rb_str_new2(data->argv[index]), rb_intern_freeze, 0)
);
}
return rb_funcall(result_rb, rb_intern_freeze, 0);
}
#endif // KERNAUX_VERSION_WITH_CMDLINE

View file

@ -1,45 +0,0 @@
#include "dynarg.h"
struct DynArg DynArg_create()
{
struct DynArg dynarg;
DynArg_init(&dynarg);
return dynarg;
}
void DynArg_init(struct DynArg *const dynarg)
{
dynarg->use_dbl = false;
dynarg->dbl = 0.0;
dynarg->arg.str = "";
}
void DynArg_use_char(struct DynArg *const dynarg, const char chr)
{
dynarg->use_dbl = false;
dynarg->arg.chr = chr;
}
void DynArg_use_double(struct DynArg *const dynarg, const double dbl)
{
dynarg->use_dbl = true;
dynarg->dbl = dbl;
}
void DynArg_use_long_long(struct DynArg *const dynarg, const long long ll)
{
dynarg->use_dbl = false;
dynarg->arg.ll = ll;
}
void DynArg_use_str(struct DynArg *const dynarg, const char *const str)
{
dynarg->use_dbl = false;
dynarg->arg.str = str;
}
void DynArg_use_unsigned_long_long(struct DynArg *const dynarg, const unsigned long long ull)
{
dynarg->use_dbl = false;
dynarg->arg.ull = ull;
}

View file

@ -1,42 +0,0 @@
#ifndef INCLUDED_DYNARG
#define INCLUDED_DYNARG
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <kernaux/macro.h>
#include <kernaux/macro/packing_start.run>
struct DynArg {
bool use_dbl;
double dbl;
// TODO: check if this will work on different endianness.
union {
char chr;
long long ll;
const char *str;
unsigned long long ull;
} KERNAUX_PACKED arg;
}
KERNAUX_PACKED;
#include <kernaux/macro/packing_end.run>
struct DynArg DynArg_create();
void DynArg_init(struct DynArg *dynarg);
void DynArg_use_char(struct DynArg *dynarg, char chr);
void DynArg_use_double(struct DynArg *dynarg, double dbl);
void DynArg_use_long_long(struct DynArg *dynarg, long long ll);
void DynArg_use_str(struct DynArg *dynarg, const char *str);
void DynArg_use_unsigned_long_long(struct DynArg *dynarg, unsigned long long ull);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,14 +0,0 @@
# frozen_string_literal: true
require 'mkmf'
$CFLAGS += ' -pedantic -Wall -Wextra'
raise 'libkernaux not found' unless have_library 'kernaux'
raise 'kernaux_assert_do not found' unless have_func 'kernaux_assert_do'
unless have_var 'kernaux_assert_cb', 'kernaux.h'
raise 'kernaux_assert_cb not found'
end
raise 'can\'t create Makefile' unless create_makefile 'kernaux/default'

View file

@ -1,34 +0,0 @@
#include "main.h"
ID rb_intern_call = Qnil;
ID rb_intern_freeze = Qnil;
ID rb_intern_LESS = Qnil;
ID rb_intern_new = Qnil;
VALUE rb_KernAux = Qnil;
VALUE rb_KernAux_Error = Qnil;
void Init_default()
{
rb_gc_register_mark_object(ID2SYM(rb_intern_call = rb_intern("call")));
rb_gc_register_mark_object(ID2SYM(rb_intern_freeze = rb_intern("freeze")));
rb_gc_register_mark_object(ID2SYM(rb_intern_LESS = rb_intern("<")));
rb_gc_register_mark_object(ID2SYM(rb_intern_new = rb_intern("new")));
rb_gc_register_mark_object(rb_KernAux = rb_define_module("KernAux"));
rb_gc_register_mark_object(rb_KernAux_Error =
rb_define_class_under(rb_KernAux, "Error", rb_eRuntimeError));
init_version();
init_assert();
#ifdef KERNAUX_VERSION_WITH_CMDLINE
init_cmdline();
#endif // KERNAUX_VERSION_WITH_CMDLINE
#ifdef KERNAUX_VERSION_WITH_NTOA
init_ntoa();
#endif // KERNAUX_VERSION_WITH_NTOA
#ifdef KERNAUX_VERSION_WITH_PRINTF
init_printf();
#endif // KERNAUX_VERSION_WITH_PRINTF
}

View file

@ -1,34 +0,0 @@
#ifndef __MAIN_H__
#define __MAIN_H__
#include <kernaux.h>
#include <ruby.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
extern ID rb_intern_call;
extern ID rb_intern_freeze;
extern ID rb_intern_LESS;
extern ID rb_intern_new;
extern VALUE rb_KernAux;
extern VALUE rb_KernAux_Error;
void init_version();
void init_assert();
#ifdef KERNAUX_VERSION_WITH_CMDLINE
void init_cmdline();
#endif // KERNAUX_VERSION_WITH_CMDLINE
#ifdef KERNAUX_VERSION_WITH_NTOA
void init_ntoa();
#endif // KERNAUX_VERSION_WITH_NTOA
#ifdef KERNAUX_VERSION_WITH_PRINTF
void init_printf();
#endif // KERNAUX_VERSION_WITH_PRINTF
#endif

View file

@ -1,254 +0,0 @@
#include "main.h"
#ifdef KERNAUX_VERSION_WITH_NTOA
static VALUE rb_KernAux_utoa(int argc, const VALUE *argv, VALUE self);
static VALUE rb_KernAux_itoa(int argc, const VALUE *argv, VALUE self);
static VALUE rb_KernAux_utoa2(VALUE self, VALUE number);
static VALUE rb_KernAux_itoa2(VALUE self, VALUE number);
static VALUE rb_KernAux_utoa8(VALUE self, VALUE number);
static VALUE rb_KernAux_itoa8(VALUE self, VALUE number);
static VALUE rb_KernAux_utoa10(VALUE self, VALUE number);
static VALUE rb_KernAux_itoa10(VALUE self, VALUE number);
static VALUE rb_KernAux_utoa16(VALUE self, VALUE number);
static VALUE rb_KernAux_itoa16(VALUE self, VALUE number);
static ID rb_intern_b = Qnil;
static ID rb_intern_B = Qnil;
static ID rb_intern_h = Qnil;
static ID rb_intern_H = Qnil;
static ID rb_intern_o = Qnil;
static ID rb_intern_O = Qnil;
static ID rb_intern_d = Qnil;
static ID rb_intern_D = Qnil;
static ID rb_intern_x = Qnil;
static ID rb_intern_X = Qnil;
static VALUE rb_KernAux_InvalidNtoaBaseError = Qnil;
static VALUE rb_KernAux_TooLongNtoaPrefixError = Qnil;
static int convert_base(VALUE base);
void init_ntoa()
{
rb_gc_register_mark_object(ID2SYM(rb_intern_b = rb_intern("b")));
rb_gc_register_mark_object(ID2SYM(rb_intern_B = rb_intern("B")));
rb_gc_register_mark_object(ID2SYM(rb_intern_h = rb_intern("h")));
rb_gc_register_mark_object(ID2SYM(rb_intern_H = rb_intern("H")));
rb_gc_register_mark_object(ID2SYM(rb_intern_o = rb_intern("o")));
rb_gc_register_mark_object(ID2SYM(rb_intern_O = rb_intern("O")));
rb_gc_register_mark_object(ID2SYM(rb_intern_d = rb_intern("d")));
rb_gc_register_mark_object(ID2SYM(rb_intern_D = rb_intern("D")));
rb_gc_register_mark_object(ID2SYM(rb_intern_x = rb_intern("x")));
rb_gc_register_mark_object(ID2SYM(rb_intern_X = rb_intern("X")));
rb_gc_register_mark_object(rb_KernAux_InvalidNtoaBaseError =
rb_define_class_under(rb_KernAux, "InvalidNtoaBaseError",
rb_KernAux_Error));
rb_gc_register_mark_object(rb_KernAux_TooLongNtoaPrefixError =
rb_define_class_under(rb_KernAux, "TooLongNtoaPrefixError",
rb_KernAux_Error));
rb_define_singleton_method(rb_KernAux, "utoa", rb_KernAux_utoa, -1);
rb_define_singleton_method(rb_KernAux, "itoa", rb_KernAux_itoa, -1);
rb_define_singleton_method(rb_KernAux, "utoa2", rb_KernAux_utoa2, 1);
rb_define_singleton_method(rb_KernAux, "itoa2", rb_KernAux_itoa2, 1);
rb_define_singleton_method(rb_KernAux, "utoa8", rb_KernAux_utoa8, 1);
rb_define_singleton_method(rb_KernAux, "itoa8", rb_KernAux_itoa8, 1);
rb_define_singleton_method(rb_KernAux, "utoa10", rb_KernAux_utoa10, 1);
rb_define_singleton_method(rb_KernAux, "itoa10", rb_KernAux_itoa10, 1);
rb_define_singleton_method(rb_KernAux, "utoa16", rb_KernAux_utoa16, 1);
rb_define_singleton_method(rb_KernAux, "itoa16", rb_KernAux_itoa16, 1);
}
VALUE rb_KernAux_utoa(const int argc, const VALUE *argv, const VALUE self)
{
if (argc < 2 || argc > 3) {
rb_raise(
rb_eArgError,
"wrong number of arguments (given %d, expected 2..3)",
argc
);
}
VALUE number_rb = argv[0];
VALUE base_rb = argv[1];
VALUE prefix_rb = argc == 3 ? argv[2] : Qnil;
const uint64_t number = NUM2ULL(number_rb);
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
}
const char *prefix = NULL;
long prefix_len = 0;
if (!NIL_P(prefix_rb)) {
prefix = StringValueCStr(prefix_rb);
prefix_len = RSTRING_LEN(prefix_rb);
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",
prefix_len
);
}
}
char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE + prefix_len];
kernaux_utoa(number, buffer, convert_base(base_rb), prefix);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_itoa(const int argc, const VALUE *argv, const VALUE self)
{
if (argc < 2 || argc > 3) {
rb_raise(
rb_eArgError,
"wrong number of arguments (given %d, expected 2..3)",
argc
);
}
VALUE number_rb = argv[0];
VALUE base_rb = argv[1];
VALUE prefix_rb = argc == 3 ? argv[2] : Qnil;
const int64_t number = NUM2LL(number_rb);
const char *prefix = NULL;
long prefix_len = 0;
if (!NIL_P(prefix_rb)) {
prefix = StringValueCStr(prefix_rb);
prefix_len = RSTRING_LEN(prefix_rb);
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",
prefix_len
);
}
}
char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE + prefix_len];
kernaux_itoa(number, buffer, convert_base(base_rb), prefix);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_utoa2(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const uint64_t number = NUM2ULL(number_rb);
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA2_BUFFER_SIZE];
kernaux_utoa2(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_itoa2(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const int64_t number = NUM2LL(number_rb);
char buffer[KERNAUX_ITOA2_BUFFER_SIZE];
kernaux_itoa2(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_utoa8(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const uint64_t number = NUM2ULL(number_rb);
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA8_BUFFER_SIZE];
kernaux_utoa8(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_itoa8(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const int64_t number = NUM2LL(number_rb);
char buffer[KERNAUX_ITOA8_BUFFER_SIZE];
kernaux_itoa8(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_utoa10(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const uint64_t number = NUM2ULL(number_rb);
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA10_BUFFER_SIZE];
kernaux_utoa10(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_itoa10(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const int64_t number = NUM2LL(number_rb);
char buffer[KERNAUX_ITOA10_BUFFER_SIZE];
kernaux_itoa10(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_utoa16(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const uint64_t number = NUM2ULL(number_rb);
if (rb_funcall(number_rb, rb_intern_LESS, 1, INT2FIX(0))) {
rb_raise(rb_eRangeError, "can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA16_BUFFER_SIZE];
kernaux_utoa16(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
VALUE rb_KernAux_itoa16(
const VALUE self_rb KERNAUX_UNUSED,
const VALUE number_rb
) {
const int64_t number = NUM2LL(number_rb);
char buffer[KERNAUX_ITOA16_BUFFER_SIZE];
kernaux_itoa16(number, buffer);
return rb_funcall(rb_str_new2(buffer), rb_intern_freeze, 0);
}
int convert_base(const VALUE base_rb)
{
if (TYPE(base_rb) == T_SYMBOL) {
const ID base_id = SYM2ID(base_rb);
if (base_id == rb_intern_b) return 'b';
else if (base_id == rb_intern_B) return 'B';
else if (base_id == rb_intern_h) return 'h';
else if (base_id == rb_intern_H) return 'H';
else if (base_id == rb_intern_o) return 'o';
else if (base_id == rb_intern_O) return 'O';
else if (base_id == rb_intern_d) return 'd';
else if (base_id == rb_intern_D) return 'D';
else if (base_id == rb_intern_x) return 'x';
else if (base_id == rb_intern_X) return 'X';
else {
rb_raise(rb_KernAux_InvalidNtoaBaseError, "invalid base");
}
} else {
return NUM2INT(base_rb);
}
}
#endif // KERNAUX_VERSION_WITH_NTOA

View file

@ -1,137 +0,0 @@
#include "main.h"
#include "dynarg.h"
#define BUFFER_SIZE 4096
#ifdef KERNAUX_VERSION_WITH_PRINTF
/**
* Typical `printf`.
*
* @param format [String] format string
* @return [String] formatted output
*
* @example
* KernAux.sprintf 'foo%*scar%d', 5, 'bar', 123
* #=> "foo barcar123"
*/
static VALUE rb_KernAux_sprintf(int argc, VALUE *argv, VALUE self);
void init_printf()
{
rb_define_singleton_method(rb_KernAux, "sprintf", rb_KernAux_sprintf, -1);
}
#define TAKE_ARG \
if (arg_index >= argc) rb_raise(rb_eArgError, "too few arguments"); \
VALUE arg_rb = argv[arg_index++]; \
do {} while (0)
VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self)
{
if (argc == 0) rb_raise(rb_eArgError, "too few arguments");
const char *format = StringValueCStr(argv[0]);
int arg_index = 1;
VALUE result = rb_str_new_literal("");
while (*format) {
if (*format != '%') {
rb_str_cat(result, format, 1);
++format;
continue;
}
++format;
struct KernAux_PrintfFmt_Spec spec =
KernAux_PrintfFmt_Spec_create_out(&format);
if (spec.set_width) {
TAKE_ARG;
KernAux_PrintfFmt_Spec_set_width(&spec, NUM2INT(arg_rb));
}
if (spec.set_precision) {
TAKE_ARG;
KernAux_PrintfFmt_Spec_set_precision(&spec, NUM2INT(arg_rb));
}
struct DynArg dynarg = DynArg_create();
if (spec.type == KERNAUX_PRINTF_FMT_TYPE_INT) {
TAKE_ARG;
DynArg_use_long_long(&dynarg, NUM2LL(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_UINT) {
TAKE_ARG;
DynArg_use_unsigned_long_long(&dynarg, NUM2ULL(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_FLOAT ||
spec.type == KERNAUX_PRINTF_FMT_TYPE_EXP)
{
TAKE_ARG;
DynArg_use_double(&dynarg, NUM2DBL(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_CHAR) {
TAKE_ARG;
Check_Type(arg_rb, T_STRING);
DynArg_use_char(&dynarg, *StringValuePtr(arg_rb));
} else if (spec.type == KERNAUX_PRINTF_FMT_TYPE_STR) {
TAKE_ARG;
Check_Type(arg_rb, T_STRING);
DynArg_use_str(&dynarg, StringValueCStr(arg_rb));
}
// 1 additional byte for the '%' character.
// 1 additional byte for the terminating '\0' character.
char old_format[2 + spec.format_limit - spec.format_start];
memset(old_format, '\0', sizeof(old_format));
old_format[0] = '%';
strncpy(&old_format[1], spec.format_start, sizeof(old_format) - 2);
char buffer[BUFFER_SIZE];
int slen;
if (spec.set_width) {
if (spec.set_precision) {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, spec.precision,
dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, spec.precision,
dynarg.arg);
}
} else {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.width, dynarg.arg);
}
}
} else {
if (spec.set_precision) {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.precision, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format,
spec.precision, dynarg.arg);
}
} else {
if (dynarg.use_dbl) {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.dbl);
} else {
slen = kernaux_snprintf(buffer, BUFFER_SIZE, old_format, dynarg.arg);
}
}
}
rb_str_cat(result, buffer, slen);
}
if (arg_index < argc) rb_raise(rb_eArgError, "too many arguments");
return rb_funcall(result, rb_intern_freeze, 0);
}
#endif // KERNAUX_VERSION_WITH_PRINTF

View file

@ -1,47 +0,0 @@
#include "main.h"
static VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self);
static VALUE rb_KernAux_Version_with_ntoaQN(VALUE self);
static VALUE rb_KernAux_Version_with_printfQN(VALUE self);
static VALUE rb_KernAux_Version = Qnil;
void init_version()
{
rb_gc_register_mark_object(rb_KernAux_Version =
rb_define_module_under(rb_KernAux, "Version"));
rb_define_singleton_method(rb_KernAux_Version, "with_cmdline?",
rb_KernAux_Version_with_cmdlineQN, 0);
rb_define_singleton_method(rb_KernAux_Version, "with_ntoa?",
rb_KernAux_Version_with_ntoaQN, 0);
rb_define_singleton_method(rb_KernAux_Version, "with_printf?",
rb_KernAux_Version_with_printfQN, 0);
}
VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self)
{
#ifdef KERNAUX_VERSION_WITH_CMDLINE
return Qtrue;
#else
return Qfalse;
#endif
}
VALUE rb_KernAux_Version_with_ntoaQN(VALUE self)
{
#ifdef KERNAUX_VERSION_WITH_NTOA
return Qtrue;
#else
return Qfalse;
#endif
}
VALUE rb_KernAux_Version_with_printfQN(VALUE self)
{
#ifdef KERNAUX_VERSION_WITH_PRINTF
return Qtrue;
#else
return Qfalse;
#endif
}

View file

@ -1,59 +0,0 @@
# frozen_string_literal: true
require_relative 'lib/kernaux/version'
Gem::Specification.new do |spec|
repo = 'https://github.com/tailix/libkernaux'
home = "#{repo}/tree/master/bindings/ruby"
bugs = "#{repo}/issues"
docs = "https://www.rubydoc.info/gems/kernaux/#{KernAux::VERSION}"
spec.name = 'kernaux'
spec.version = KernAux::VERSION
spec.license = 'MIT'
spec.homepage = home
spec.platform = Gem::Platform::RUBY
spec.required_ruby_version = '~> 3.0'
spec.authors = ['Alex Kotov']
spec.email = %w[kotovalexarian@gmail.com]
spec.summary =
'Binding to libkernaux - auxiliary library for kernel development'
spec.description = <<~DESCRIPTION.split("\n").map(&:strip).join ' '
Binding to libkernaux - auxiliary library for kernel development.
DESCRIPTION
spec.metadata['rubygems_mfa_required'] = 'true'
spec.metadata['homepage_uri'] = home
spec.metadata['source_code_uri'] = home
spec.metadata['bug_tracker_uri'] = bugs
spec.metadata['documentation_uri'] = docs
spec.bindir = 'exe'
spec.require_paths = ['lib']
spec.files = Dir.chdir File.expand_path __dir__ do
`git ls-files -z`.split("\x0").reject do |f|
f.match %r{\A(?:test|spec|features)/}
end
end
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename f }
spec.extensions << 'ext/default/extconf.rb'
spec.add_development_dependency 'bundler', '~> 2.2'
spec.add_development_dependency 'pry', '~> 0.14'
spec.add_development_dependency 'rake', '~> 13.0'
spec.add_development_dependency 'rake-compiler', '~> 1.1'
spec.add_development_dependency 'rspec', '~> 3.10'
spec.add_development_dependency 'rubocop', '~> 1.25'
spec.add_development_dependency 'rubocop-performance', '~> 1.13'
spec.add_development_dependency 'rubocop-rake', '~> 0.6'
spec.add_development_dependency 'rubocop-rspec', '~> 2.7'
spec.add_development_dependency 'simplecov', '~> 0.21'
spec.add_development_dependency 'yard', '~> 0.9'
end

View file

@ -1,19 +0,0 @@
# frozen_string_literal: true
##
# Binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
# library for kernel development.
#
module KernAux
end
require_relative 'kernaux/version'
# Native extensions
require_relative 'kernaux/default'
# Non-standard directory structure
require_relative 'kernaux/assert'
require_relative 'kernaux/cmdline'
require_relative 'kernaux/errors'
require_relative 'kernaux/ntoa'

View file

@ -1,58 +0,0 @@
# frozen_string_literal: true
# rubocop:disable Style/Documentation
begin; end
module KernAux
# Default callback for assertions.
# @see .assert_cb
DEFAULT_ASSERT_CB = @assert_cb = lambda { |file, line, msg|
raise AssertError, "#{file}:#{line}:#{msg}"
}
# @!scope class
##
# @!attribute [rw] assert_cb
# Panic callback.
#
# @return [Proc]
#
# @api unsafe
#
# @see .panic
# @see .assert_do
##
##
# Raise assertion with implicit file and line, retrieved from `caller`, and
# explicit message.
#
# @param msg [String] any message
# @return [nil]
#
# @raise [AssertError] if {.assert_cb} have not been changed
#
# @see .assert_do Explicit file and line.
#
def self.panic(msg)
file, line = caller(1..1).first.split(':')[0..1]
assert_do file, Integer(line), msg
end
##
# @!method assert_do(file, line, msg)
# Raise assertion with explicit file, line and message.
#
# @param file [String] file name, usually from `__FILE__`
# @param line [Integer] line number, usually from `__LINE__`
# @param msg [String] any message
# @return [nil]
#
# @raise [AssertError] if {.assert_cb} have not been changed
#
# @see .panic Implicit file and line
##
end
# rubocop:enable Style/Documentation

View file

@ -1,20 +0,0 @@
# frozen_string_literal: true
# rubocop:disable Style/Documentation
begin; end
module KernAux
# @!scope class
##
# @!method cmdline(str)
# Parse command line.
#
# @param str [String] command line string
# @return [Array<String>] command line arguments
#
# @raise [CmdlineError] syntax is invalid
##
end
# rubocop:enable Style/Documentation

View file

@ -1,39 +0,0 @@
# frozen_string_literal: true
module KernAux
##
# Our base class for runtime errors.
#
class Error < RuntimeError; end
##
# Raised when assertion has failed or panic has been called.
#
# @see .panic
# @see .assert_do
#
class AssertError < Error; end
##
# Raised when command line parsing goes wrong.
#
# @see .cmdline
#
class CmdlineError < Error; end
##
# Raised when integer base is invalid.
#
# @see .utoa
# @see .itoa
#
class InvalidNtoaBaseError < Error; end
##
# Raised when prefix is too long.
#
# @see .utoa
# @see .itoa
#
class TooLongNtoaPrefixError < Error; end
end

View file

@ -1,136 +0,0 @@
# frozen_string_literal: true
# rubocop:disable Style/Documentation
begin; end
module KernAux
# @!scope class
##
# @!method utoa(number, base, prefix)
# Convert `uint64_t` to a string in multiple numeral systems.
#
# Base can be a positive or negative integer between 2 and 36, or a symbol
# which is an alias to a valid integer value. Positive integers and lowercase
# symbols mean lowercase output when base is greater than 10. Negative
# integers and uppercase symbols mean uppercase output when base is greater
# than 10. Aliases are: `:b`, `:B` - 2; `:o`, `:O` - 8; `:d`, `:D` - 10; `:h`,
# `:x` - 16 (lowercase); `:H`, `:X` - -10 (uppercase).
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @param base [Integer, Symbol] base of a numeral system
# @param prefix [nil, String] string to put before a number
# @return [String]
#
# @raise [RangeError] number is out of range
# @raise [InvalidNtoaBaseError] base is invalid
# @raise [TooLongNtoaPrefixError] prefix is too long
#
# @see .itoa Convert signed integers
##
##
# @!method itoa(number, base, prefix)
# Convert `int64_t` to a string in multiple numeral systems.
#
# Base can be a positive or negative integer between 2 and 36, or a symbol
# which is an alias to a valid integer value. Positive integers and lowercase
# symbols mean lowercase output when base is greater than 10. Negative
# integers and uppercase symbols mean uppercase output when base is greater
# than 10. Aliases are: `:b`, `:B` - 2; `:o`, `:O` - 8; `:d`, `:D` - 10; `:h`,
# `:x` - 16 (lowercase); `:H`, `:X` - -10 (uppercase).
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @param base [Integer, Symbol] base of a numeral system
# @param prefix [nil, String] string to put between a sign and a number
# @return [String]
#
# @raise [RangeError] number is out of range
# @raise [InvalidNtoaBaseError] base is invalid
# @raise [TooLongNtoaPrefixError] prefix is too long
#
# @see .utoa Convert unsigned integers
##
##
# @!method utoa2(number)
# Convert `uint64_t` to a binary string.
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method itoa2(number)
# Convert `int64_t` to a binary string.
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method utoa8(number)
# Convert `uint64_t` to a octal string.
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method itoa8(number)
# Convert `int64_t` to a octal string.
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method utoa10(number)
# Convert `uint64_t` to a decimal string.
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method itoa10(number)
# Convert `int64_t` to a decimal string.
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method utoa16(number)
# Convert `uint64_t` to a hexadecimal string.
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
##
# @!method itoa16(number)
# Convert `int64_t` to a hexadecimal string.
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @return [String]
#
# @raise [RangeError] number is out of range
##
end
# rubocop:enable Style/Documentation

View file

@ -1,13 +0,0 @@
# frozen_string_literal: true
module KernAux
# Gem version.
VERSION = '0.7.0'
##
# This module includes functions to determine if specific features are
# supported by the library.
#
module Version
end
end

View file

@ -1,32 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe KernAux, '.panic' do
subject(:panic) { described_class.panic msg }
let(:msg) { 'Hello, World!' }
specify do
expect { panic }.to \
raise_error described_class::AssertError, /\A#{__FILE__}:\d+:#{msg}\z/
end
context 'when custom assertion callback has beed set' do
around do |example|
described_class.assert_cb = lambda { |file, line, msg|
raise "file: #{file.inspect}, line: #{line}, msg: #{msg.inspect}"
}
example.run
ensure
described_class.assert_cb = described_class::DEFAULT_ASSERT_CB
end
specify do
expect { panic }.to raise_error(
RuntimeError,
/\Afile: #{__FILE__.inspect}, line: \d+, msg: #{msg.inspect}\z/,
)
end
end
end

View file

@ -1,115 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_cmdline? and RSpec.describe KernAux, '.cmdline' do
subject(:cmdline) { described_class.cmdline str }
let(:str) { 'foo bar\\ baz "car cdr"' }
it { is_expected.to be_instance_of Array }
it { is_expected.to be_frozen }
it { is_expected.to all be_instance_of String }
it { is_expected.to all be_frozen }
it { is_expected.to eq ['foo', 'bar baz', 'car cdr'] }
context 'when str is empty' do
let(:str) { '' }
it { is_expected.to eq [] }
end
context 'when str has invalid type' do
let(:str) { 123 }
specify { expect { cmdline }.to raise_error TypeError }
end
context 'when str has EOL after backslash' do
let(:str) { '\\' }
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'EOL after backslash'
end
end
context 'when str has EOL after backslash inside quote' do
let(:str) { '"\\' }
specify do
expect { cmdline }.to raise_error \
described_class::CmdlineError, 'EOL after backslash inside quote'
end
end
context 'when str has unescaped quotation mark' do
let(:str) { 'foo"' }
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'unescaped quotation mark'
end
end
context 'when str has EOL inside quote' do
let(:str) { '"' }
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'EOL inside quote'
end
end
context 'when there are not too many args' do
let(:str) { 'a ' * 256 }
it { is_expected.to eq ['a'] * 256 }
end
context 'when there are too many args' do
let(:str) { 'a ' * 257 }
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'too many args'
end
end
context 'when args don\'t cause buffer overflow' do
let(:str) { 'a' * 4095 }
it { is_expected.to eq ['a' * 4095] }
end
context 'when args cause buffer overflow' do
let(:str) { 'a' * 4096 }
specify do
expect { cmdline }.to \
raise_error described_class::CmdlineError, 'EOF or buffer overflow'
end
end
context 'using fixtures' do
cmdline_yml =
File.expand_path('../../../../../fixtures/cmdline.yml', __dir__)
YAML.safe_load_file(cmdline_yml).each do |test|
escape_str = lambda do |str|
eval "\"#{str}\"", binding, __FILE__, __LINE__ # "str"
end
cmdline = escape_str.call test['cmdline']
arg_count_max = test['arg_count_max']
buffer_size = test['buffer_size']
result = test['result']&.map(&escape_str)
next unless arg_count_max.nil? && buffer_size.nil? && !result.nil?
it "transforms #{cmdline.inspect} to #{result.inspect}" do
expect(described_class.cmdline(cmdline)).to eq result
end
end
end
end

View file

@ -1,70 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.itoa10' do
subject(:itoa10) { described_class.itoa10 number }
let(:number) { rand((-2**63)..(2**63 - 1)) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0' }
end
context 'when number is 1' do
let(:number) { 1 }
it { is_expected.to eq '1' }
end
context 'when number is -1' do
let(:number) { -1 }
it { is_expected.to eq '-1' }
end
context 'when number is min int64_t' do
let(:number) { -2**63 }
it { is_expected.to eq number.to_s }
end
context 'when number is max int64_t' do
let(:number) { 2**63 - 1 }
it { is_expected.to eq number.to_s }
end
context 'when number is lesser than min uint64_t' do
let(:number) { -2**63 - 1 }
specify do
expect { itoa10 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**63 }
specify do
expect { itoa10 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand((-2**63)..(2**63 - 1)).to_s }
specify do
expect { itoa10 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,72 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.itoa16' do
subject(:itoa16) { described_class.itoa16 number }
let(:number) { rand((-2**63)..(2**63 - 1)) }
def sign = number < 0 ? '-' : ''
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{sign}0x#{number.abs.to_s(16)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0x0' }
end
context 'when number is 1' do
let(:number) { 1 }
it { is_expected.to eq '0x1' }
end
context 'when number is -1' do
let(:number) { -1 }
it { is_expected.to eq '-0x1' }
end
context 'when number is min int64_t' do
let(:number) { -2**63 }
it { is_expected.to eq "-0x#{number.abs.to_s(16)}" }
end
context 'when number is max int64_t' do
let(:number) { 2**63 - 1 }
it { is_expected.to eq "0x#{number.to_s(16)}" }
end
context 'when number is lesser than min uint64_t' do
let(:number) { -2**63 - 1 }
specify do
expect { itoa16 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**63 }
specify do
expect { itoa16 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand((-2**63)..(2**63 - 1)).to_s }
specify do
expect { itoa16 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,72 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.itoa2' do
subject(:itoa2) { described_class.itoa2 number }
let(:number) { rand((-2**63)..(2**63 - 1)) }
def sign = number < 0 ? '-' : ''
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{sign}0b#{number.abs.to_s(2)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0b0' }
end
context 'when number is 1' do
let(:number) { 1 }
it { is_expected.to eq '0b1' }
end
context 'when number is -1' do
let(:number) { -1 }
it { is_expected.to eq '-0b1' }
end
context 'when number is min int64_t' do
let(:number) { -2**63 }
it { is_expected.to eq "-0b#{number.abs.to_s(2)}" }
end
context 'when number is max int64_t' do
let(:number) { 2**63 - 1 }
it { is_expected.to eq "0b#{number.to_s(2)}" }
end
context 'when number is lesser than min uint64_t' do
let(:number) { -2**63 - 1 }
specify do
expect { itoa2 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**63 }
specify do
expect { itoa2 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand((-2**63)..(2**63 - 1)).to_s }
specify do
expect { itoa2 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,72 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.itoa8' do
subject(:itoa8) { described_class.itoa8 number }
let(:number) { rand((-2**63)..(2**63 - 1)) }
def sign = number < 0 ? '-' : ''
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{sign}0o#{number.abs.to_s(8)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0o0' }
end
context 'when number is 1' do
let(:number) { 1 }
it { is_expected.to eq '0o1' }
end
context 'when number is -1' do
let(:number) { -1 }
it { is_expected.to eq '-0o1' }
end
context 'when number is min int64_t' do
let(:number) { -2**63 }
it { is_expected.to eq "-0o#{number.abs.to_s(8)}" }
end
context 'when number is max int64_t' do
let(:number) { 2**63 - 1 }
it { is_expected.to eq "0o#{number.to_s(8)}" }
end
context 'when number is lesser than min uint64_t' do
let(:number) { -2**63 - 1 }
specify do
expect { itoa8 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**63 }
specify do
expect { itoa8 }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand((-2**63)..(2**63 - 1)).to_s }
specify do
expect { itoa8 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,245 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.itoa' do
subject(:itoa) { described_class.itoa number, base, prefix }
let(:number) { rand((-2**63)..(2**63 - 1)) }
let(:base) { rand 2..36 }
let(:prefix) { [nil, ''].sample }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq '0' }
end
context 'when number is 1' do
let(:number) { 1 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq '1' }
end
context 'when number is -1' do
let(:number) { -1 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq '-1' }
end
context 'when number is min int64_t' do
let(:number) { -2**63 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when number is max int64_t' do
let(:number) { 2**63 - 1 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when number is lesser than min uint64_t' do
let(:number) { -2**63 - 1 }
specify do
expect { itoa }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**63 }
specify do
expect { itoa }.to raise_error \
RangeError, 'bignum too big to convert into `long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand((-2**63)..(2**63 - 1)).to_s }
specify do
expect { itoa }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
context 'when base is negative' do
let(:base) { -rand(2..36) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(-base).upcase }
end
context 'when base is :b' do
let(:base) { :b }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 2 }
end
context 'when base is :B:' do
let(:base) { :B }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 2 }
end
context 'when base is :o' do
let(:base) { :o }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 8 }
end
context 'when base is :O' do
let(:base) { :O }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 8 }
end
context 'when base is :d' do
let(:base) { :d }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
end
context 'when base is :D' do
let(:base) { :D }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
end
context 'when base is :h' do
let(:base) { :h }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 16 }
end
context 'when base is :x' do
let(:base) { :x }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 16 }
end
context 'when base is :H' do
let(:base) { :H }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(16).upcase }
end
context 'when base is :X' do
let(:base) { :X }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(16).upcase }
end
context 'when base is an invalid symbol' do
let(:base) { :foo }
specify do
expect { itoa }.to \
raise_error described_class::InvalidNtoaBaseError, 'invalid base'
end
end
context 'when no prefix is given' do
subject(:itoa) { described_class.itoa number, base }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is nil' do
let(:prefix) { nil }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is empty' do
let(:prefix) { '' }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is present' do
let(:prefix) { 'foo' }
def sign = number < 0 ? '-' : ''
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{sign}foo#{number.abs.to_s(base)}" }
end
context 'when prefix is not a string' do
let(:prefix) { 123 }
specify do
expect { itoa }.to raise_error(
TypeError,
"no implicit conversion of #{prefix.class} into String",
)
end
end
context 'when prefix has max length' do
let(:prefix) { 'a' * 100 }
def sign = number < 0 ? '-' : ''
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{sign}#{prefix}#{number.abs.to_s(base)}" }
end
context 'when prefix is too long' do
let(:prefix) { 'a' * 101 }
specify do
expect { itoa }.to raise_error(
described_class::TooLongNtoaPrefixError,
"prefix length #{prefix.length} is too long",
)
end
end
end

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.utoa10' do
subject(:utoa10) { described_class.utoa10 number }
let(:number) { rand 0..(2**64 - 1) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0' }
end
context 'when number is max uint64_t' do
let(:number) { 2**64 - 1 }
it { is_expected.to eq number.to_s }
end
context 'when number is -1' do
let(:number) { -1 }
specify do
expect { utoa10 }.to \
raise_error RangeError, 'can\'t convert negative number to uint64_t'
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**64 }
specify do
expect { utoa10 }.to raise_error \
RangeError, 'bignum too big to convert into `unsigned long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand(0..(2**64 - 1)).to_s }
specify do
expect { utoa10 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.utoa16' do
subject(:utoa16) { described_class.utoa16 number }
let(:number) { rand 0..(2**64 - 1) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "0x#{number.to_s(16)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0x0' }
end
context 'when number is max uint64_t' do
let(:number) { 2**64 - 1 }
it { is_expected.to eq "0x#{number.to_s(16)}" }
end
context 'when number is -1' do
let(:number) { -1 }
specify do
expect { utoa16 }.to \
raise_error RangeError, 'can\'t convert negative number to uint64_t'
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**64 }
specify do
expect { utoa16 }.to raise_error \
RangeError, 'bignum too big to convert into `unsigned long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand(0..(2**64 - 1)).to_s }
specify do
expect { utoa16 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.utoa2' do
subject(:utoa2) { described_class.utoa2 number }
let(:number) { rand 0..(2**64 - 1) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "0b#{number.to_s(2)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0b0' }
end
context 'when number is max uint64_t' do
let(:number) { 2**64 - 1 }
it { is_expected.to eq "0b#{number.to_s(2)}" }
end
context 'when number is -1' do
let(:number) { -1 }
specify do
expect { utoa2 }.to \
raise_error RangeError, 'can\'t convert negative number to uint64_t'
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**64 }
specify do
expect { utoa2 }.to raise_error \
RangeError, 'bignum too big to convert into `unsigned long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand(0..(2**64 - 1)).to_s }
specify do
expect { utoa2 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.utoa8' do
subject(:utoa8) { described_class.utoa8 number }
let(:number) { rand 0..(2**64 - 1) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "0o#{number.to_s(8)}" }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to eq '0o0' }
end
context 'when number is max uint64_t' do
let(:number) { 2**64 - 1 }
it { is_expected.to eq "0o#{number.to_s(8)}" }
end
context 'when number is -1' do
let(:number) { -1 }
specify do
expect { utoa8 }.to \
raise_error RangeError, 'can\'t convert negative number to uint64_t'
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**64 }
specify do
expect { utoa8 }.to raise_error \
RangeError, 'bignum too big to convert into `unsigned long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand(0..(2**64 - 1)).to_s }
specify do
expect { utoa8 }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
end

View file

@ -1,217 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_ntoa? and RSpec.describe KernAux, '.utoa' do
subject(:utoa) { described_class.utoa number, base, prefix }
let(:number) { rand 0..(2**64 - 1) }
let(:base) { rand 2..36 }
let(:prefix) { [nil, ''].sample }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
context 'when number is 0' do
let(:number) { 0 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq '0' }
end
context 'when number is max uint64_t' do
let(:number) { 2**64 - 1 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when number is -1' do
let(:number) { -1 }
specify do
expect { utoa }.to \
raise_error RangeError, 'can\'t convert negative number to uint64_t'
end
end
context 'when number is greater than max uint64_t' do
let(:number) { 2**64 }
specify do
expect { utoa }.to raise_error \
RangeError, 'bignum too big to convert into `unsigned long long\''
end
end
context 'when number is not numeric' do
let(:number) { rand(0..(2**64 - 1)).to_s }
specify do
expect { utoa }.to raise_error \
TypeError, 'no implicit conversion from string'
end
end
context 'when base is negative' do
let(:base) { -rand(2..36) }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(-base).upcase }
end
context 'when base is :b' do
let(:base) { :b }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 2 }
end
context 'when base is :B:' do
let(:base) { :B }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 2 }
end
context 'when base is :o' do
let(:base) { :o }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 8 }
end
context 'when base is :O' do
let(:base) { :O }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 8 }
end
context 'when base is :d' do
let(:base) { :d }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
end
context 'when base is :D' do
let(:base) { :D }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s }
end
context 'when base is :h' do
let(:base) { :h }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 16 }
end
context 'when base is :x' do
let(:base) { :x }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s 16 }
end
context 'when base is :H' do
let(:base) { :H }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(16).upcase }
end
context 'when base is :X' do
let(:base) { :X }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s(16).upcase }
end
context 'when base is an invalid symbol' do
let(:base) { :foo }
specify do
expect { utoa }.to \
raise_error described_class::InvalidNtoaBaseError, 'invalid base'
end
end
context 'when no prefix is given' do
subject(:utoa) { described_class.utoa number, base }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is nil' do
let(:prefix) { nil }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is empty' do
let(:prefix) { '' }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq number.to_s base }
end
context 'when prefix is present' do
let(:prefix) { 'foo' }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{prefix}#{number.to_s(base)}" }
end
context 'when prefix is not a string' do
let(:prefix) { 123 }
specify do
expect { utoa }.to raise_error(
TypeError,
"no implicit conversion of #{prefix.class} into String",
)
end
end
context 'when prefix has max length' do
let(:prefix) { 'a' * 100 }
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq "#{prefix}#{number.to_s(base)}" }
end
context 'when prefix is too long' do
let(:prefix) { 'a' * 101 }
specify do
expect { utoa }.to raise_error(
described_class::TooLongNtoaPrefixError,
"prefix length #{prefix.length} is too long",
)
end
end
end

View file

@ -1,85 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
KernAux::Version.with_printf? and RSpec.describe KernAux, '.sprintf' do
subject :sprintf do
described_class.sprintf 'Hello, %s!', 'World'
end
it { is_expected.to be_instance_of String }
it { is_expected.to be_frozen }
it { is_expected.to eq 'Hello, World!' }
context 'when there are too many arguments' do
[
['Hello!', 'World!'],
['Hello, %s!', 'World', 'Alex'],
].each do |args|
it "raises on #{args.inspect}" do
expect { described_class.sprintf(*args) }.to \
raise_error ArgumentError, 'too many arguments'
end
end
end
context 'when there are too few arguments' do
[
[],
['Hello, %s!'],
['Hello, %*s!', 20],
['Hello, %.*s!', 20],
['Hello, %*.*s!', 20, 20],
].each do |args|
it "raises on #{args.inspect}" do
expect { described_class.sprintf(*args) }.to \
raise_error ArgumentError, 'too few arguments'
end
end
end
[
['', 'using regular fixtures'],
['_orig', 'using original fixtures'],
].each do |(suffix, description)|
context description do
printf_yml = File.expand_path(
"../../../../../fixtures/printf#{suffix}.yml",
__dir__,
)
YAML.safe_load_file(printf_yml).each do |test|
expected = test['result']
format = ''
args = []
test['args'].each do |arg|
if arg.is_a? String
format += arg
else
format += arg[0]
arg[1..].each do |item|
if item.is_a? Array
if item.length == 1
args << item[0]
elsif item[0] == 'long long'
args << item[1]
else
raise "Unknown format: #{args.inspect}"
end
else
args << item
end
end
end
end
it "transforms (#{format.inspect}, #{args.inspect[1...-1]}) " \
"to #{expected.inspect}" do
expect(described_class.sprintf(format, *args)).to eq expected
end
end
end
end
end

View file

@ -1,11 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe KernAux do
describe '::VERSION' do
specify do
expect(described_class::VERSION).to match(/\A\d+\.\d+\.\d+\z/)
end
end
end

View file

@ -1,106 +0,0 @@
# frozen_string_literal: true
# This should be on the top of the file.
require 'simplecov'
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need
# it.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
require 'kernaux'
require 'yaml'
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
# have no way to turn it off -- the option exists only for backwards
# compatibility in RSpec 3). It causes shared context metadata to be
# inherited by the metadata hash of host groups and examples, rather than
# triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups
# This allows you to limit a spec run to individual examples or groups
# you care about by tagging them with `:focus` metadata. When nothing
# is tagged with `:focus`, all examples get run. RSpec also provides
# aliases for `it`, `describe`, and `context` that include `:focus`
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
config.filter_run_when_matching :focus
# Allows RSpec to persist some state between runs in order to support
# the `--only-failures` and `--next-failure` CLI options. We recommend
# you configure your source control system to ignore this file.
config.example_status_persistence_file_path = 'spec/examples.txt'
# Limits the available syntax to the non-monkey patched syntax that is
# recommended. For more details, see:
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
config.disable_monkey_patching!
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = 'doc'
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
end

View file

@ -1,2 +0,0 @@
/Cargo.lock
/target/

View file

@ -1,5 +0,0 @@
[workspace]
members = [
"kernaux",
"kernaux-sys",
]

View file

@ -1,23 +0,0 @@
[package]
name = "kernaux-sys"
version = "0.7.0"
authors = ["Alex Kotov <kotovalexarian@gmail.com>"]
edition = "2021"
description = "Unsafe no-std binding to libkernaux - auxiliary library for kernel development"
readme = true
homepage = "https://github.com/tailix/libkernaux/tree/master/bindings/rust"
repository = "https://github.com/tailix/libkernaux/tree/master/bindings/rust"
license = "MIT"
keywords = ["ffi", "no_std", "no-std", "embedded", "bindings"]
categories = ["embedded", "external-ffi-bindings", "no-std", "parsing"]
publish = true
[features]
default = ["cmdline", "ntoa"]
cmdline = []
ntoa = []
[dependencies.libc]
version = "0.2.113"
default-features = false
features = ["extra_traits"]

View file

@ -1,8 +0,0 @@
kernaux_sys
===========
[![Build status](https://github.com/tailix/libkernaux/actions/workflows/rust.yml/badge.svg)](https://github.com/tailix/libkernaux/actions/workflows/rust.yml)
[![Build status (FreeBSD)](https://api.cirrus-ci.com/github/tailix/libkernaux.svg?task=Rust%20(FreeBSD))](https://cirrus-ci.com/github/tailix/libkernaux)
Unsafe no-std binding to [libkernaux](https://github.com/tailix/libkernaux) -
auxiliary library for kernel development.

View file

@ -1,67 +0,0 @@
use libc::{c_char, c_int};
pub type AssertCB = unsafe extern "C" fn(*const c_char, c_int, *const c_char);
#[link(name = "kernaux")]
extern "C" {
#[link_name = "kernaux_assert_do"]
pub fn assert_do(file: *const c_char, line: c_int, msg: *const c_char);
#[link_name = "kernaux_assert_cb"]
pub static mut assert_cb: Option<AssertCB>;
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::{CStr, CString};
use std::ptr::null;
static mut LAST_FILE: *const c_char = null();
static mut LAST_LINE: c_int = 0;
static mut LAST_MSG: *const c_char = null();
unsafe extern "C" fn some_assert_cb(
file: *const c_char,
line: c_int,
msg: *const c_char,
) {
LAST_FILE = file;
LAST_LINE = line;
LAST_MSG = msg;
}
#[test]
fn default() {
unsafe {
assert_cb = None;
assert!(assert_cb.is_none());
assert_cb = Some(some_assert_cb);
match assert_cb {
None => panic!(),
Some(actual_assert_cb) => {
assert!(actual_assert_cb == some_assert_cb)
}
}
let file_cstr = CString::new("foo.rs").unwrap();
let msg_cstr = CString::new("bar").unwrap();
assert_do(
file_cstr.as_ptr() as *const c_char,
123,
msg_cstr.as_ptr() as *const c_char,
);
let file = CStr::from_ptr(LAST_FILE).to_str().unwrap();
let line = LAST_LINE;
let msg = CStr::from_ptr(LAST_MSG).to_str().unwrap();
assert_eq!(file, "foo.rs");
assert_eq!(line, 123);
assert_eq!(msg, "bar");
}
}
}

View file

@ -1,70 +0,0 @@
use libc::{c_char, size_t};
pub const ERROR_MSG_SIZE_MAX: usize = 256;
pub const ERROR_MSG_SLEN_MAX: usize = ERROR_MSG_SIZE_MAX - 1;
#[link(name = "kernaux")]
extern "C" {
#[link_name = "kernaux_cmdline"]
// TODO: Rust's "bool" is not guaranteed to be compatible with C's one
pub fn cmdline(
cmdline: *const c_char,
error_msg: *mut c_char,
argc: *mut size_t,
argv: *mut *mut c_char,
buffer: *mut c_char,
arg_count_max: size_t,
buffer_size: size_t,
) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::{CStr, CString};
const ARG_COUNT_MAX: usize = 100;
const BUFFER_SIZE: usize = 4096;
#[test]
fn default() {
let cmdline = CString::new("foo bar\\ baz \"car cdr\"").unwrap();
let mut error_msg: [c_char; ERROR_MSG_SIZE_MAX] =
[0; ERROR_MSG_SIZE_MAX];
let mut argc: size_t = 0;
let mut argv: [*mut c_char; ARG_COUNT_MAX] =
[0 as *mut c_char; ARG_COUNT_MAX];
let mut buffer: [c_char; BUFFER_SIZE] = [0; BUFFER_SIZE];
unsafe {
assert!(super::cmdline(
cmdline.as_ptr(),
error_msg.as_mut_ptr(),
&mut argc,
argv.as_mut_ptr(),
buffer.as_mut_ptr(),
ARG_COUNT_MAX,
BUFFER_SIZE,
));
}
assert_eq!(
unsafe { CStr::from_ptr(error_msg.as_ptr()) }
.to_str()
.unwrap(),
"",
);
assert_eq!(argc, 3);
assert_eq!(unsafe { CStr::from_ptr(argv[0]) }.to_str().unwrap(), "foo");
assert_eq!(
unsafe { CStr::from_ptr(argv[1]) }.to_str().unwrap(),
"bar baz",
);
assert_eq!(
unsafe { CStr::from_ptr(argv[2]) }.to_str().unwrap(),
"car cdr",
);
}
}

View file

@ -1,19 +0,0 @@
#![no_std]
#[cfg(test)]
extern crate std;
pub mod assert;
pub mod version;
#[cfg(feature = "cmdline")]
pub mod cmdline;
#[cfg(feature = "ntoa")]
pub mod ntoa;
pub use assert::*;
#[cfg(feature = "cmdline")]
pub use cmdline::cmdline;
#[cfg(feature = "ntoa")]
pub use ntoa::{MAX_PREFIX_LEN as NTOA_MAX_PREFIX_LEN, *};

View file

@ -1,266 +0,0 @@
use libc::{c_char, c_int};
pub const MAX_PREFIX_LEN: usize = 100;
pub const UTOA_MIN_BUFFER_SIZE: usize = 64 + 1;
pub const ITOA_MIN_BUFFER_SIZE: usize = 65 + 1;
pub const UTOA2_BUFFER_SIZE: usize = 64 + 2 + 1;
pub const ITOA2_BUFFER_SIZE: usize = 65 + 2 + 1;
pub const UTOA8_BUFFER_SIZE: usize = 21 + 2 + 1;
pub const ITOA8_BUFFER_SIZE: usize = 22 + 2 + 1;
pub const UTOA10_BUFFER_SIZE: usize = 20 + 1;
pub const ITOA10_BUFFER_SIZE: usize = 20 + 1;
pub const UTOA16_BUFFER_SIZE: usize = 16 + 2 + 1;
pub const ITOA16_BUFFER_SIZE: usize = 17 + 2 + 1;
#[link(name = "kernaux")]
extern "C" {
#[link_name = "kernaux_utoa"]
pub fn utoa(
value: u64,
buffer: *mut c_char,
base: c_int,
prefix: *const c_char,
) -> *mut c_char;
#[link_name = "kernaux_itoa"]
pub fn itoa(
value: i64,
buffer: *mut c_char,
base: c_int,
prefix: *const c_char,
) -> *mut c_char;
#[link_name = "kernaux_utoa2"]
pub fn utoa2(value: u64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_itoa2"]
pub fn itoa2(value: i64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_utoa8"]
pub fn utoa8(value: u64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_itoa8"]
pub fn itoa8(value: i64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_utoa10"]
pub fn utoa10(value: u64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_itoa10"]
pub fn itoa10(value: i64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_utoa16"]
pub fn utoa16(value: u64, buffer: *mut c_char) -> *mut c_char;
#[link_name = "kernaux_itoa16"]
pub fn itoa16(value: i64, buffer: *mut c_char) -> *mut c_char;
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::{CStr, CString};
use std::ptr::null;
fn empty_prefix() -> CString {
CString::new("").unwrap()
}
fn foo_prefix() -> CString {
CString::new("foo").unwrap()
}
#[test]
fn test_utoa() {
let mut buffer: [i8; UTOA_MIN_BUFFER_SIZE + 3] =
[0; UTOA_MIN_BUFFER_SIZE + 3];
let empty_pfx = empty_prefix();
let foo_pfx = foo_prefix();
let end: *mut c_char =
unsafe { utoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, null()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
let end: *mut c_char = unsafe {
utoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, empty_pfx.as_ptr())
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
let end: *mut c_char = unsafe {
utoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, foo_pfx.as_ptr())
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "foo123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(6) });
}
#[test]
fn test_itoa() {
let mut buffer: [i8; ITOA_MIN_BUFFER_SIZE + 3] =
[0; ITOA_MIN_BUFFER_SIZE + 3];
let empty_pfx = empty_prefix();
let foo_pfx = foo_prefix();
let end: *mut c_char =
unsafe { itoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, null()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
let end: *mut c_char = unsafe {
itoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, empty_pfx.as_ptr())
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
let end: *mut c_char = unsafe {
itoa(0x123, buffer.as_mut_ptr(), 'x' as c_int, foo_pfx.as_ptr())
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "foo123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(6) });
let end: *mut c_char =
unsafe { itoa(-0x123, buffer.as_mut_ptr(), 'x' as c_int, null()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(4) });
let end: *mut c_char = unsafe {
itoa(
-0x123,
buffer.as_mut_ptr(),
'x' as c_int,
empty_pfx.as_ptr(),
)
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(4) });
let end: *mut c_char = unsafe {
itoa(-0x123, buffer.as_mut_ptr(), 'x' as c_int, foo_pfx.as_ptr())
};
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-foo123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(7) });
}
#[test]
fn test_utoa2() {
let mut buffer: [i8; UTOA2_BUFFER_SIZE] = [0; UTOA2_BUFFER_SIZE];
let end: *mut c_char = unsafe { utoa2(123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0b1111011");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(9) });
}
#[test]
fn test_itoa2() {
let mut buffer: [i8; ITOA2_BUFFER_SIZE] = [0; ITOA2_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa2(123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0b1111011");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(9) });
let mut buffer: [i8; ITOA2_BUFFER_SIZE] = [0; ITOA2_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa2(-123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-0b1111011");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(10) });
}
#[test]
fn test_utoa8() {
let mut buffer: [i8; UTOA8_BUFFER_SIZE] = [0; UTOA8_BUFFER_SIZE];
let end: *mut c_char = unsafe { utoa8(0o123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0o123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(5) });
}
#[test]
fn test_itoa8() {
let mut buffer: [i8; ITOA8_BUFFER_SIZE] = [0; ITOA8_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa8(0o123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0o123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(5) });
let mut buffer: [i8; ITOA8_BUFFER_SIZE] = [0; ITOA8_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa8(-0o123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-0o123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(6) });
}
#[test]
fn test_utoa10() {
let mut buffer: [i8; UTOA10_BUFFER_SIZE] = [0; UTOA10_BUFFER_SIZE];
let end: *mut c_char = unsafe { utoa10(123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
}
#[test]
fn test_itoa10() {
let mut buffer: [i8; ITOA10_BUFFER_SIZE] = [0; ITOA10_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa10(123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(3) });
let mut buffer: [i8; ITOA10_BUFFER_SIZE] = [0; ITOA10_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa10(-123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(4) });
}
#[test]
fn test_utoa16() {
let mut buffer: [i8; UTOA16_BUFFER_SIZE] = [0; UTOA16_BUFFER_SIZE];
let end: *mut c_char = unsafe { utoa16(0x123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0x123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(5) });
}
#[test]
fn test_itoa16() {
let mut buffer: [i8; ITOA16_BUFFER_SIZE] = [0; ITOA16_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa16(0x123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "0x123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(5) });
let mut buffer: [i8; ITOA16_BUFFER_SIZE] = [0; ITOA16_BUFFER_SIZE];
let end: *mut c_char = unsafe { itoa16(-0x123, buffer.as_mut_ptr()) };
let result =
unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
assert_eq!(result, "-0x123");
assert_eq!(end, unsafe { buffer.as_mut_ptr().offset(6) });
}
}

View file

@ -1,7 +0,0 @@
pub fn with_cmdline() -> bool {
cfg!(feature = "cmdline")
}
pub fn with_ntoa() -> bool {
cfg!(feature = "ntoa")
}

View file

@ -1,30 +0,0 @@
[package]
name = "kernaux"
version = "0.7.0"
authors = ["Alex Kotov <kotovalexarian@gmail.com>"]
edition = "2021"
description = "Safe binding to libkernaux - auxiliary library for kernel development"
readme = true
homepage = "https://github.com/tailix/libkernaux/tree/master/bindings/rust"
repository = "https://github.com/tailix/libkernaux/tree/master/bindings/rust"
license = "MIT"
keywords = ["ffi", "embedded", "bindings"]
categories = ["api-bindings", "embedded", "parsing"]
publish = true
[features]
default = ["cmdline", "ntoa"]
cmdline = ["kernaux-sys/cmdline"]
ntoa = ["kernaux-sys/ntoa"]
[dependencies]
ctor = "0.1.22"
[dependencies.kernaux-sys]
version = "0.7.0"
default-features = false
path = "../kernaux-sys"
[dependencies.libc]
version = "0.2.113"
default-features = false

View file

@ -1,8 +0,0 @@
kernaux
=======
[![Build status](https://github.com/tailix/libkernaux/actions/workflows/rust.yml/badge.svg)](https://github.com/tailix/libkernaux/actions/workflows/rust.yml)
[![Build status (FreeBSD)](https://api.cirrus-ci.com/github/tailix/libkernaux.svg?task=Rust%20(FreeBSD))](https://cirrus-ci.com/github/tailix/libkernaux)
Safe binding to [libkernaux](https://github.com/tailix/libkernaux) - auxiliary
library for kernel development.

View file

@ -1,33 +0,0 @@
use ctor::ctor;
use libc::{c_char, c_int};
use std::ffi::CStr;
#[ctor]
unsafe fn ctor() {
kernaux_sys::assert_cb = Some(assert_cb);
}
unsafe extern "C" fn assert_cb(
file: *const c_char,
line: c_int,
msg: *const c_char,
) {
let file = CStr::from_ptr(file).to_str().unwrap();
let msg = CStr::from_ptr(msg).to_str().unwrap();
panic!("{}:{}:{}", file, line, msg);
}
#[cfg(test)]
mod tests {
use std::ffi::CString;
#[test]
#[should_panic(expected = "foo.rs:123:bar")]
fn default() {
let file = CString::new("foo.rs").unwrap();
let msg = CString::new("bar").unwrap();
unsafe { kernaux_sys::assert_do(file.as_ptr(), 123, msg.as_ptr()) }
}
}

View file

@ -1,52 +0,0 @@
pub mod assert;
pub mod version;
#[cfg(feature = "ntoa")]
pub mod ntoa;
#[cfg(feature = "ntoa")]
pub use ntoa::{
itoa, itoa10, itoa16, itoa2, itoa8, utoa, utoa10, utoa16, utoa2, utoa8,
Config as NtoaConfig, Error as NtoaError, Result as NtoaResult,
};
#[cfg(test)]
#[cfg(feature = "ntoa")]
mod tests {
use super::*;
#[test]
#[cfg(feature = "ntoa")]
fn test_ntoa() {
assert_eq!(NtoaConfig::try_from('x').unwrap().base(), 16);
assert_eq!(NtoaConfig::try_from('x').unwrap().uppercase(), false);
assert_eq!(NtoaConfig::try_from('x'), NtoaConfig::try_from(16));
assert_eq!(NtoaConfig::try_from('X'), NtoaConfig::try_from(-16));
assert_eq!(utoa(123, Default::default(), None), Ok("123".into()));
assert_eq!(itoa(123, Default::default(), None), Ok("123".into()));
assert_eq!(itoa(-123, Default::default(), None), Ok("-123".into()));
assert_eq!(
utoa(123, Default::default(), Some("foo")),
Ok("foo123".into()),
);
assert_eq!(
itoa(123, Default::default(), Some("foo")),
Ok("foo123".into()),
);
assert_eq!(
itoa(-123, Default::default(), Some("foo")),
Ok("-foo123".into()),
);
assert_eq!(utoa2(123), "0b1111011");
assert_eq!(itoa2(123), "0b1111011");
assert_eq!(utoa8(0o123), "0o123");
assert_eq!(itoa8(0o123), "0o123");
assert_eq!(utoa10(123), "123");
assert_eq!(itoa10(123), "123");
assert_eq!(utoa16(0x123), "0x123");
assert_eq!(itoa16(0x123), "0x123");
}
}

View file

@ -1,771 +0,0 @@
use kernaux_sys::ntoa::{
itoa as kernaux_itoa, itoa10 as kernaux_itoa10, itoa16 as kernaux_itoa16,
itoa2 as kernaux_itoa2, itoa8 as kernaux_itoa8, utoa as kernaux_utoa,
utoa10 as kernaux_utoa10, utoa16 as kernaux_utoa16, utoa2 as kernaux_utoa2,
utoa8 as kernaux_utoa8, ITOA10_BUFFER_SIZE, ITOA16_BUFFER_SIZE,
ITOA2_BUFFER_SIZE, ITOA8_BUFFER_SIZE, ITOA_MIN_BUFFER_SIZE, MAX_PREFIX_LEN,
UTOA10_BUFFER_SIZE, UTOA16_BUFFER_SIZE, UTOA2_BUFFER_SIZE,
UTOA8_BUFFER_SIZE, UTOA_MIN_BUFFER_SIZE,
};
use std::ffi::{CStr, CString, NulError};
use std::ptr::null;
use std::str::Utf8Error;
use libc::c_int;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Config {
base: u8,
uppercase: bool,
}
pub type Result = std::result::Result<String, Error>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
PrefixTooLong(usize),
PrefixIncludesNull(NulError),
Utf8(Utf8Error),
}
pub fn utoa(value: u64, config: Config, prefix: Option<&str>) -> Result {
let prefix = if let Some(prefix) = prefix {
if prefix.len() > MAX_PREFIX_LEN {
return Err(Error::PrefixTooLong(prefix.len()));
}
Some(CString::new(prefix)?)
} else {
None
};
utoac(value, config, prefix)
}
pub fn itoa(value: i64, config: Config, prefix: Option<&str>) -> Result {
let prefix = if let Some(prefix) = prefix {
if prefix.len() > MAX_PREFIX_LEN {
return Err(Error::PrefixTooLong(prefix.len()));
}
Some(CString::new(prefix)?)
} else {
None
};
itoac(value, config, prefix)
}
fn utoac(value: u64, config: Config, prefix: Option<CString>) -> Result {
let mut buffer: [i8; UTOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN] =
[0; UTOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN];
unsafe {
kernaux_utoa(
value,
buffer.as_mut_ptr(),
config.to_c_int(),
prefix
.as_ref()
.map(|prefix| prefix.as_ptr())
.unwrap_or(null()),
);
};
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str()?;
Ok(String::from(result))
}
fn itoac(value: i64, config: Config, prefix: Option<CString>) -> Result {
let mut buffer: [i8; ITOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN] =
[0; ITOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN];
unsafe {
kernaux_itoa(
value,
buffer.as_mut_ptr(),
config.to_c_int(),
prefix
.as_ref()
.map(|prefix| prefix.as_ptr())
.unwrap_or(null()),
);
};
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str()?;
Ok(String::from(result))
}
pub fn utoa2(value: u64) -> String {
let mut buffer: [i8; UTOA2_BUFFER_SIZE] = [0; UTOA2_BUFFER_SIZE];
unsafe { kernaux_utoa2(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn itoa2(value: i64) -> String {
let mut buffer: [i8; ITOA2_BUFFER_SIZE] = [0; ITOA2_BUFFER_SIZE];
unsafe { kernaux_itoa2(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn utoa8(value: u64) -> String {
let mut buffer: [i8; UTOA8_BUFFER_SIZE] = [0; UTOA8_BUFFER_SIZE];
unsafe { kernaux_utoa8(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn itoa8(value: i64) -> String {
let mut buffer: [i8; ITOA8_BUFFER_SIZE] = [0; ITOA8_BUFFER_SIZE];
unsafe { kernaux_itoa8(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn utoa10(value: u64) -> String {
let mut buffer: [i8; UTOA10_BUFFER_SIZE] = [0; UTOA10_BUFFER_SIZE];
unsafe { kernaux_utoa10(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn itoa10(value: i64) -> String {
let mut buffer: [i8; ITOA10_BUFFER_SIZE] = [0; ITOA10_BUFFER_SIZE];
unsafe { kernaux_itoa10(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn utoa16(value: u64) -> String {
let mut buffer: [i8; UTOA16_BUFFER_SIZE] = [0; UTOA16_BUFFER_SIZE];
unsafe { kernaux_utoa16(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
pub fn itoa16(value: i64) -> String {
let mut buffer: [i8; ITOA16_BUFFER_SIZE] = [0; ITOA16_BUFFER_SIZE];
unsafe { kernaux_itoa16(value, buffer.as_mut_ptr()) };
let result = unsafe { CStr::from_ptr(buffer.as_ptr()) }.to_str().unwrap();
String::from(result)
}
impl Default for Config {
fn default() -> Self {
Self {
base: 10,
uppercase: false,
}
}
}
impl Config {
pub fn base(&self) -> u8 {
self.base
}
pub fn uppercase(&self) -> bool {
self.uppercase
}
fn to_c_int(self) -> c_int {
if self.uppercase {
(-(self.base as i8)).into()
} else {
self.base.into()
}
}
}
impl From<NulError> for Error {
fn from(nul_error: NulError) -> Self {
Self::PrefixIncludesNull(nul_error)
}
}
impl From<Utf8Error> for Error {
fn from(utf8_error: Utf8Error) -> Self {
Self::Utf8(utf8_error)
}
}
impl TryFrom<char> for Config {
type Error = ();
fn try_from(value: char) -> std::result::Result<Self, Self::Error> {
let base: i64 = match value {
'b' | 'B' => 2,
'o' | 'O' => 8,
'd' | 'D' => 10,
'h' | 'x' => 16,
'H' | 'X' => -16,
_ => return Err(()),
};
base.try_into()
}
}
impl TryFrom<u64> for Config {
type Error = ();
fn try_from(value: u64) -> std::result::Result<Self, Self::Error> {
if (2..=36).contains(&value) {
Ok(Self {
base: value as u8,
uppercase: false,
})
} else {
Err(())
}
}
}
impl TryFrom<i64> for Config {
type Error = ();
fn try_from(value: i64) -> std::result::Result<Self, Self::Error> {
let uppercase = value < 0;
let value = if value < 0 { -value } else { value };
if (2..=36).contains(&value) {
Ok(Self {
base: value as u8,
uppercase,
})
} else {
Err(())
}
}
}
impl TryFrom<u32> for Config {
type Error = ();
fn try_from(value: u32) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as u64)
}
}
impl TryFrom<i32> for Config {
type Error = ();
fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as i64)
}
}
impl TryFrom<u16> for Config {
type Error = ();
fn try_from(value: u16) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as u64)
}
}
impl TryFrom<i16> for Config {
type Error = ();
fn try_from(value: i16) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as i64)
}
}
impl TryFrom<u8> for Config {
type Error = ();
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as u64)
}
}
impl TryFrom<i8> for Config {
type Error = ();
fn try_from(value: i8) -> std::result::Result<Self, Self::Error> {
Self::try_from(value as i64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_utoa_prefix() {
assert_eq!(
utoa(123, Default::default(), Some("foo")),
Ok("foo123".into()),
);
assert_eq!(
utoa(
123,
Default::default(),
Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
),
Ok("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa123".into()),
);
assert_eq!(
utoa(
123,
Default::default(),
Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
),
Err(Error::PrefixTooLong(101)),
);
}
#[test]
fn test_itoa_prefix() {
assert_eq!(
itoa(123, Default::default(), Some("foo")),
Ok("foo123".into()),
);
assert_eq!(
itoa(-123, Default::default(), Some("foo")),
Ok("-foo123".into()),
);
assert_eq!(
itoa(
123,
Default::default(),
Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
),
Ok("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa123".into()),
);
assert_eq!(
itoa(
123,
Default::default(),
Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
),
Err(Error::PrefixTooLong(101)),
);
}
#[test]
fn test_utoa() {
// binary
assert_eq!(
utoa(0b10110, 'b'.try_into().unwrap(), None),
Ok("10110".into()),
);
assert_eq!(
utoa(0b10110, 'B'.try_into().unwrap(), None),
Ok("10110".into()),
);
assert_eq!(
utoa(0b10110, 2.try_into().unwrap(), None),
Ok("10110".into()),
);
assert_eq!(
utoa(0b10110, (-2).try_into().unwrap(), None),
Ok("10110".into()),
);
// octal
assert_eq!(
utoa(0o123, 'o'.try_into().unwrap(), None),
Ok("123".into()),
);
assert_eq!(
utoa(0o123, 'O'.try_into().unwrap(), None),
Ok("123".into()),
);
assert_eq!(utoa(0o123, 8.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(
utoa(0o123, (-8).try_into().unwrap(), None),
Ok("123".into()),
);
// decimal
assert_eq!(utoa(123, Default::default(), None), Ok("123".into()));
assert_eq!(utoa(123, 'd'.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(utoa(123, 'D'.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(utoa(123, 10.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(
utoa(123, (-10).try_into().unwrap(), None),
Ok("123".into()),
);
// hexadecimal
assert_eq!(
utoa(0x123cafe, 'x'.try_into().unwrap(), None),
Ok("123cafe".into()),
);
assert_eq!(
utoa(0x123cafe, 16.try_into().unwrap(), None),
Ok("123cafe".into()),
);
assert_eq!(
utoa(0x123cafe, 'X'.try_into().unwrap(), None),
Ok("123CAFE".into()),
);
assert_eq!(
utoa(0x123cafe, (-16).try_into().unwrap(), None),
Ok("123CAFE".into()),
);
// random base: 14
assert_eq!(
utoa(123456, 14.try_into().unwrap(), None),
Ok("32dc4".into()),
);
assert_eq!(
utoa(123456, (-14).try_into().unwrap(), None),
Ok("32DC4".into()),
);
}
#[test]
fn test_itoa() {
// binary
assert_eq!(
itoa(0b10110, 'b'.try_into().unwrap(), None),
Ok("10110".into()),
);
assert_eq!(
itoa(-0b10110, 'B'.try_into().unwrap(), None),
Ok("-10110".into()),
);
assert_eq!(
itoa(-0b10110, 2.try_into().unwrap(), None),
Ok("-10110".into()),
);
assert_eq!(
itoa(0b10110, (-2).try_into().unwrap(), None),
Ok("10110".into()),
);
// octal
assert_eq!(
itoa(-0o123, 'o'.try_into().unwrap(), None),
Ok("-123".into()),
);
assert_eq!(
itoa(0o123, 'O'.try_into().unwrap(), None),
Ok("123".into()),
);
assert_eq!(itoa(0o123, 8.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(
itoa(-0o123, (-8).try_into().unwrap(), None),
Ok("-123".into()),
);
// decimal
assert_eq!(itoa(123, Default::default(), None), Ok("123".into()));
assert_eq!(
itoa(-123, 'd'.try_into().unwrap(), None),
Ok("-123".into()),
);
assert_eq!(
itoa(-123, 'D'.try_into().unwrap(), None),
Ok("-123".into()),
);
assert_eq!(itoa(123, 10.try_into().unwrap(), None), Ok("123".into()));
assert_eq!(
itoa(123, (-10).try_into().unwrap(), None),
Ok("123".into()),
);
// hexadecimal
assert_eq!(
itoa(-0x123cafe, 'x'.try_into().unwrap(), None),
Ok("-123cafe".into()),
);
assert_eq!(
itoa(0x123cafe, 16.try_into().unwrap(), None),
Ok("123cafe".into()),
);
assert_eq!(
itoa(0x123cafe, 'X'.try_into().unwrap(), None),
Ok("123CAFE".into()),
);
assert_eq!(
itoa(-0x123cafe, (-16).try_into().unwrap(), None),
Ok("-123CAFE".into()),
);
// random base: 14
assert_eq!(
itoa(123456, 14.try_into().unwrap(), None),
Ok("32dc4".into()),
);
assert_eq!(
itoa(-123456, (-14).try_into().unwrap(), None),
Ok("-32DC4".into()),
);
assert_eq!(
itoa(-123456, 14.try_into().unwrap(), None),
Ok("-32dc4".into()),
);
assert_eq!(
itoa(123456, (-14).try_into().unwrap(), None),
Ok("32DC4".into()),
);
}
#[test]
fn test_utoa2() {
assert_eq!(utoa2(0), "0b0");
assert_eq!(utoa2(1), "0b1");
assert_eq!(utoa2(123), "0b1111011");
assert_eq!(
utoa2(u64::MAX),
"0b1111111111111111111111111111111111111111111111111111111111111111",
);
}
#[test]
fn test_itoa2() {
assert_eq!(itoa2(0), "0b0");
assert_eq!(itoa2(1), "0b1");
assert_eq!(itoa2(-1), "-0b1");
assert_eq!(itoa2(123), "0b1111011");
assert_eq!(itoa2(-123), "-0b1111011");
assert_eq!(
itoa2(i64::MAX),
"0b111111111111111111111111111111111111111111111111111111111111111",
);
assert_eq!(
itoa2(i64::MIN),
"-0b1000000000000000000000000000000000000000000000000000000000000000",
);
}
#[test]
fn test_utoa8() {
assert_eq!(utoa8(0), "0o0");
assert_eq!(utoa8(1), "0o1");
assert_eq!(utoa8(0o123), "0o123");
assert_eq!(utoa8(u64::MAX), "0o1777777777777777777777");
}
#[test]
fn test_itoa8() {
assert_eq!(itoa8(0), "0o0");
assert_eq!(itoa8(1), "0o1");
assert_eq!(itoa8(-1), "-0o1");
assert_eq!(itoa8(0o123), "0o123");
assert_eq!(itoa8(-0o123), "-0o123");
assert_eq!(itoa8(i64::MAX), "0o777777777777777777777");
assert_eq!(itoa8(i64::MIN), "-0o1000000000000000000000");
}
#[test]
fn test_utoa10() {
assert_eq!(utoa10(0), "0");
assert_eq!(utoa10(1), "1");
assert_eq!(utoa10(123), "123");
assert_eq!(utoa10(u64::MAX), "18446744073709551615");
}
#[test]
fn test_itoa10() {
assert_eq!(itoa10(0), "0");
assert_eq!(itoa10(1), "1");
assert_eq!(itoa10(-1), "-1");
assert_eq!(itoa10(123), "123");
assert_eq!(itoa10(-123), "-123");
assert_eq!(itoa10(i64::MAX), "9223372036854775807");
assert_eq!(itoa10(i64::MIN), "-9223372036854775808");
}
#[test]
fn test_utoa16() {
assert_eq!(utoa16(0), "0x0");
assert_eq!(utoa16(1), "0x1");
assert_eq!(utoa16(0x123), "0x123");
assert_eq!(utoa16(u64::MAX), "0xffffffffffffffff");
}
#[test]
fn test_itoa16() {
assert_eq!(itoa16(0), "0x0");
assert_eq!(itoa16(1), "0x1");
assert_eq!(itoa16(-1), "-0x1");
assert_eq!(itoa16(0x123), "0x123");
assert_eq!(itoa16(-0x123), "-0x123");
assert_eq!(itoa16(i64::MAX), "0x7fffffffffffffff");
assert_eq!(itoa16(i64::MIN), "-0x8000000000000000");
}
#[test]
fn test_config_default() {
assert_eq!(
Config::default(),
Config {
base: 10,
uppercase: false,
},
);
}
#[test]
fn test_try_config_from_unsigned() {
assert_eq!(Config::try_from(12u8), Config::try_from(12u64));
assert_eq!(Config::try_from(12i8), Config::try_from(12i64));
assert_eq!(Config::try_from(12u16), Config::try_from(12u64));
assert_eq!(Config::try_from(12i16), Config::try_from(12i64));
assert_eq!(Config::try_from(12u32), Config::try_from(12u64));
assert_eq!(Config::try_from(12i32), Config::try_from(12i64));
}
#[test]
fn test_try_config_from_u64() {
assert_eq!(Config::try_from(0u64), Err(()));
assert_eq!(Config::try_from(1u64), Err(()));
assert_eq!(Config::try_from(37u64), Err(()));
assert_eq!(
Config::try_from(2u64),
Ok(Config {
base: 2,
uppercase: false,
}),
);
assert_eq!(
Config::try_from(10u64),
Ok(Config {
base: 10,
uppercase: false,
}),
);
assert_eq!(
Config::try_from(36u64),
Ok(Config {
base: 36,
uppercase: false,
}),
);
}
#[test]
fn test_try_config_from_i64() {
assert_eq!(Config::try_from(0i64), Err(()));
assert_eq!(Config::try_from(1i64), Err(()));
assert_eq!(Config::try_from(-1i64), Err(()));
assert_eq!(Config::try_from(37i64), Err(()));
assert_eq!(Config::try_from(-37i64), Err(()));
assert_eq!(
Config::try_from(2i64),
Ok(Config {
base: 2,
uppercase: false,
}),
);
assert_eq!(
Config::try_from(-2i64),
Ok(Config {
base: 2,
uppercase: true,
}),
);
assert_eq!(
Config::try_from(10i64),
Ok(Config {
base: 10,
uppercase: false,
}),
);
assert_eq!(
Config::try_from(-10i64),
Ok(Config {
base: 10,
uppercase: true,
}),
);
assert_eq!(
Config::try_from(36i64),
Ok(Config {
base: 36,
uppercase: false,
}),
);
assert_eq!(
Config::try_from(-36i64),
Ok(Config {
base: 36,
uppercase: true,
}),
);
}
#[test]
fn test_try_config_from_char() {
assert_eq!(Config::try_from('a'), Err(()));
assert_eq!(Config::try_from('A'), Err(()));
assert_eq!(Config::try_from('z'), Err(()));
assert_eq!(Config::try_from('Z'), Err(()));
assert_eq!(
Config::try_from('b'),
Ok(Config {
base: 2,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('B'),
Ok(Config {
base: 2,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('o'),
Ok(Config {
base: 8,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('O'),
Ok(Config {
base: 8,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('d'),
Ok(Config {
base: 10,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('D'),
Ok(Config {
base: 10,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('h'),
Ok(Config {
base: 16,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('H'),
Ok(Config {
base: 16,
uppercase: true,
}),
);
assert_eq!(
Config::try_from('x'),
Ok(Config {
base: 16,
uppercase: false,
}),
);
assert_eq!(
Config::try_from('X'),
Ok(Config {
base: 16,
uppercase: true,
}),
);
}
}

View file

@ -1 +0,0 @@
../../kernaux-sys/src/version.rs

View file

@ -1 +0,0 @@
max_width = 80