cxx2flow 0.6.3

Convert your C/C++ code to control flow chart
Documentation
use std::alloc::{
    Layout, alloc as rust_alloc, alloc_zeroed as rust_alloc_zeroed, dealloc as rust_dealloc,
    realloc as rust_realloc,
};
use std::ffi::{c_char, c_int, c_void};
use std::ptr;

const ALIGNMENT: usize = std::mem::size_of::<usize>();
const HEADER_SIZE: usize = std::mem::size_of::<usize>();

fn layout_for_allocation(size: usize) -> Option<Layout> {
    size.checked_add(HEADER_SIZE)
        .and_then(|total| Layout::from_size_align(total, ALIGNMENT).ok())
}

unsafe fn base_ptr_and_size(user_ptr: *mut u8) -> Option<(*mut u8, usize)> {
    if user_ptr.is_null() {
        return None;
    }

    let base_ptr = unsafe { user_ptr.sub(HEADER_SIZE) };
    let size = unsafe { ptr::read(base_ptr as *const usize) };
    Some((base_ptr, size))
}

unsafe fn store_size(base_ptr: *mut u8, size: usize) {
    unsafe { ptr::write(base_ptr as *mut usize, size) };
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
    if size == 0 {
        return ptr::null_mut();
    }

    let layout = match layout_for_allocation(size) {
        Some(layout) => layout,
        None => return ptr::null_mut(),
    };
    let base_ptr = unsafe { rust_alloc(layout) };
    if base_ptr.is_null() {
        return ptr::null_mut();
    }

    unsafe { store_size(base_ptr, size) };
    unsafe { base_ptr.add(HEADER_SIZE) }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut u8 {
    let user_size = match nmemb.checked_mul(size) {
        Some(total) if total != 0 => total,
        _ => return ptr::null_mut(),
    };

    let layout = match layout_for_allocation(user_size) {
        Some(layout) => layout,
        None => return ptr::null_mut(),
    };

    let base_ptr = unsafe { rust_alloc_zeroed(layout) };
    if base_ptr.is_null() {
        return ptr::null_mut();
    }

    unsafe { store_size(base_ptr, user_size) };
    unsafe { base_ptr.add(HEADER_SIZE) }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
    if ptr.is_null() {
        return unsafe { malloc(new_size) };
    }

    if new_size == 0 {
        unsafe { free(ptr) };
        return ptr::null_mut();
    }

    let (base_ptr, old_size) = match unsafe { base_ptr_and_size(ptr) } {
        Some(v) => v,
        None => return ptr::null_mut(),
    };
    let old_layout = match layout_for_allocation(old_size) {
        Some(layout) => layout,
        None => return ptr::null_mut(),
    };
    let new_layout = match layout_for_allocation(new_size) {
        Some(layout) => layout,
        None => return ptr::null_mut(),
    };

    let new_base = unsafe { rust_realloc(base_ptr, old_layout, new_layout.size()) };
    if new_base.is_null() {
        return ptr::null_mut();
    }

    unsafe { store_size(new_base, new_size) };
    unsafe { new_base.add(HEADER_SIZE) }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn free(ptr: *mut u8) {
    if ptr.is_null() {
        return;
    }

    if let Some((base_ptr, size)) = unsafe { base_ptr_and_size(ptr) } {
        if let Some(layout) = layout_for_allocation(size) {
            unsafe { rust_dealloc(base_ptr, layout) };
        }
    }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
    if s1.is_null() || s2.is_null() {
        return 0;
    }

    for index in 0..n {
        let c1 = unsafe { *s1.add(index) as u8 };
        let c2 = unsafe { *s2.add(index) as u8 };

        if c1 == 0 || c2 == 0 || c1 != c2 {
            return (c1 as i32) - (c2 as i32);
        }
    }

    0
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcmp(s1: *const c_char, s2: *const c_char) -> c_int {
    if s1.is_null() || s2.is_null() {
        return 0;
    }

    let mut index = 0usize;
    loop {
        let c1 = unsafe { *s1.add(index) as u8 };
        let c2 = unsafe { *s2.add(index) as u8 };
        if c1 == 0 || c2 == 0 || c1 != c2 {
            return (c1 as i32) - (c2 as i32);
        }
        index += 1;
    }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn strncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
    if dest.is_null() || src.is_null() {
        return dest;
    }

    for index in 0..n {
        let c = unsafe { *src.add(index) };
        unsafe { *dest.add(index) = c };
        if c == 0 {
            break;
        }
    }

    dest
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn memchr(s: *const c_void, c: c_int, n: usize) -> *mut c_void {
    if s.is_null() || n == 0 {
        return ptr::null_mut();
    }

    let bytes = s as *const u8;
    let needle = c as u8;
    for index in 0..n {
        if unsafe { *bytes.add(index) } == needle {
            return unsafe { bytes.add(index) as *mut c_void };
        }
    }
    ptr::null_mut()
}

#[unsafe(no_mangle)]
pub extern "C" fn fclose(_stream: *mut c_void) -> c_int {
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn fdopen(_fd: c_int, _mode: *const c_char) -> *mut c_void {
    ptr::null_mut()
}

#[unsafe(no_mangle)]
pub extern "C" fn clock() -> usize {
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn fwrite(
    _ptr: *const c_void,
    _size: usize,
    _nmemb: usize,
    _stream: *mut c_void,
) -> usize {
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn fputc(_c: c_int, _stream: *mut c_void) -> c_int {
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn iswspace(wc: u32) -> c_int {
    matches!(
        wc,
        0x20
            | 0x09..=0x0D
            | 0xA0
            | 0x1680
            | 0x2000..=0x200A
            | 0x2028
            | 0x2029
            | 0x202F
            | 0x205F
            | 0x3000
    ) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn iswalnum(wc: u32) -> c_int {
    (iswalpha(wc) != 0 || iswdigit(wc) != 0) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn iswdigit(wc: u32) -> c_int {
    matches!(wc, 0x30..=0x39) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn iswxdigit(wc: u32) -> c_int {
    (iswdigit(wc) != 0 || matches!(wc, 0x41..=0x46 | 0x61..=0x66)) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn iswupper(wc: u32) -> c_int {
    if (0x41..=0x5A).contains(&wc) {
        return 1;
    }
    if (0xC0..=0xD6).contains(&wc) || (0xD8..=0xDE).contains(&wc) {
        return 1;
    }
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn iswlower(wc: u32) -> c_int {
    if (0x61..=0x7A).contains(&wc) {
        return 1;
    }
    if (0xE0..=0xF6).contains(&wc) || (0xF8..=0xFF).contains(&wc) {
        return 1;
    }
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn iswpunct(wc: u32) -> c_int {
    matches!(wc, 0x21..=0x2F | 0x3A..=0x40 | 0x5B..=0x60 | 0x7B..=0x7E) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn iswalpha(wc: u32) -> c_int {
    matches!(
        wc,
        0x41..=0x5A
            | 0x61..=0x7A
            | 0xAA
            | 0xB5
            | 0xBA
            | 0xC0..=0xD6
            | 0xD8..=0xF6
            | 0xF8..=0x2C1
            | 0x2C6..=0x2D1
            | 0x2E0..=0x2E4
            | 0x2EC
            | 0x2EE
            | 0x370..=0x374
            | 0x376..=0x377
            | 0x37A..=0x37D
            | 0x37F
            | 0x386
            | 0x388..=0x38A
            | 0x38C
            | 0x38E..=0x3A1
            | 0x3A3..=0x3F5
            | 0x3F7..=0x481
            | 0x48A..=0x52F
            | 0x531..=0x556
            | 0x559
            | 0x560..=0x588
    ) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn towlower(wc: u32) -> u32 {
    if (0x41..=0x5A).contains(&wc) || (0xC0..=0xD6).contains(&wc) || (0xD8..=0xDE).contains(&wc) {
        return wc + 32;
    }
    wc
}

#[unsafe(no_mangle)]
pub extern "C" fn towupper(wc: u32) -> u32 {
    if (0x61..=0x7A).contains(&wc) || (0xE0..=0xF6).contains(&wc) || (0xF8..=0xFE).contains(&wc) {
        return wc - 32;
    }
    wc
}

#[unsafe(no_mangle)]
pub extern "C" fn fputs(_s: *const c_char, _stream: *mut c_void) -> c_int {
    0
}

#[unsafe(no_mangle)]
pub extern "C" fn abort() {}

#[unsafe(no_mangle)]
pub extern "C" fn dup(_fd: c_int) -> c_int {
    -1
}

#[cfg(target_family = "wasm")]
#[used]
static _FORCE_INCLUDE: () = {
    let _ = strncmp as *const ();
    let _ = strcmp as *const ();
    let _ = strncpy as *const ();
    let _ = memchr as *const ();
    let _ = fclose as *const ();
    let _ = fdopen as *const ();
    let _ = clock as *const ();
    let _ = fwrite as *const ();
    let _ = fputc as *const ();
    let _ = iswspace as *const ();
    let _ = iswalnum as *const ();
    let _ = iswdigit as *const ();
    let _ = iswxdigit as *const ();
    let _ = iswupper as *const ();
    let _ = iswlower as *const ();
    let _ = iswpunct as *const ();
    let _ = iswalpha as *const ();
    let _ = towlower as *const ();
    let _ = towupper as *const ();
    let _ = fputs as *const ();
    let _ = abort as *const ();
    let _ = dup as *const ();
};