forked from vitrine/wmaker
Port WINGs data.c (WMData) to Rust.
This is not tested super well, but I hope we can be rid of it soon enough. (Once we have WMPropList migrated, WMData and other WINGs data structures should be easier to prune.)
This commit is contained in:
@@ -65,7 +65,6 @@ libWINGs_la_SOURCES = \
|
||||
|
||||
libWUtil_la_SOURCES = \
|
||||
bagtree.c \
|
||||
data.c \
|
||||
error.c \
|
||||
error.h \
|
||||
findfile.c \
|
||||
|
||||
@@ -598,24 +598,10 @@ WMData* WMRetainData(WMData *aData);
|
||||
|
||||
void WMReleaseData(WMData *aData);
|
||||
|
||||
/* Adjusting capacity */
|
||||
|
||||
void WMSetDataCapacity(WMData *aData, unsigned capacity);
|
||||
|
||||
void WMSetDataLength(WMData *aData, unsigned length);
|
||||
|
||||
void WMIncreaseDataLengthBy(WMData *aData, unsigned extraLength);
|
||||
|
||||
/* Accessing data */
|
||||
|
||||
const void* WMDataBytes(WMData *aData);
|
||||
|
||||
void WMGetDataBytes(WMData *aData, void *buffer);
|
||||
|
||||
void WMGetDataBytesWithLength(WMData *aData, void *buffer, unsigned length);
|
||||
|
||||
void WMGetDataBytesWithRange(WMData *aData, void *buffer, WMRange aRange);
|
||||
|
||||
/* Testing data */
|
||||
|
||||
Bool WMIsDataEqualToData(WMData *aData, WMData *anotherData);
|
||||
@@ -630,10 +616,6 @@ void WMAppendData(WMData *aData, WMData *anotherData);
|
||||
|
||||
/* Modifying data */
|
||||
|
||||
void WMReplaceDataBytesInRange(WMData *aData, WMRange aRange, const void *bytes);
|
||||
|
||||
void WMResetDataBytesInRange(WMData *aData, WMRange aRange);
|
||||
|
||||
void WMSetData(WMData *aData, WMData *anotherData);
|
||||
|
||||
|
||||
|
||||
255
WINGs/data.c
255
WINGs/data.c
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* WINGs WMData function library
|
||||
*
|
||||
* Copyright (c) 1999-2003 Dan Pascu
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "WUtil.h"
|
||||
|
||||
typedef struct W_Data {
|
||||
unsigned length; /* How many bytes we have */
|
||||
unsigned capacity; /* How many bytes it can hold */
|
||||
unsigned growth; /* How much to grow */
|
||||
void *bytes; /* Actual data */
|
||||
unsigned retainCount;
|
||||
int format; /* 0, 8, 16 or 32 */
|
||||
} W_Data;
|
||||
|
||||
/* Creating and destroying data objects */
|
||||
|
||||
WMData *WMCreateDataWithCapacity(unsigned capacity)
|
||||
{
|
||||
WMData *aData;
|
||||
|
||||
aData = (WMData *) wmalloc(sizeof(WMData));
|
||||
|
||||
if (capacity > 0)
|
||||
aData->bytes = wmalloc(capacity);
|
||||
else
|
||||
aData->bytes = NULL;
|
||||
|
||||
aData->capacity = capacity;
|
||||
aData->growth = capacity / 2 > 0 ? capacity / 2 : 1;
|
||||
aData->length = 0;
|
||||
aData->retainCount = 1;
|
||||
aData->format = 0;
|
||||
|
||||
return aData;
|
||||
}
|
||||
|
||||
WMData *WMCreateDataWithLength(unsigned length)
|
||||
{
|
||||
WMData *aData;
|
||||
|
||||
aData = WMCreateDataWithCapacity(length);
|
||||
if (length > 0) {
|
||||
aData->length = length;
|
||||
}
|
||||
|
||||
return aData;
|
||||
}
|
||||
|
||||
WMData *WMCreateDataWithBytes(const void *bytes, unsigned length)
|
||||
{
|
||||
WMData *aData;
|
||||
|
||||
aData = WMCreateDataWithCapacity(length);
|
||||
aData->length = length;
|
||||
memcpy(aData->bytes, bytes, length);
|
||||
|
||||
return aData;
|
||||
}
|
||||
|
||||
WMData *WMCreateDataWithData(WMData * aData)
|
||||
{
|
||||
WMData *newData;
|
||||
|
||||
if (aData->length > 0) {
|
||||
newData = WMCreateDataWithBytes(aData->bytes, aData->length);
|
||||
} else {
|
||||
newData = WMCreateDataWithCapacity(0);
|
||||
}
|
||||
newData->format = aData->format;
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
WMData *WMRetainData(WMData * aData)
|
||||
{
|
||||
aData->retainCount++;
|
||||
return aData;
|
||||
}
|
||||
|
||||
void WMReleaseData(WMData * aData)
|
||||
{
|
||||
aData->retainCount--;
|
||||
if (aData->retainCount > 0)
|
||||
return;
|
||||
if (aData->bytes != NULL) {
|
||||
wfree(aData->bytes);
|
||||
}
|
||||
wfree(aData);
|
||||
}
|
||||
|
||||
/* Adjusting capacity */
|
||||
|
||||
void WMSetDataCapacity(WMData * aData, unsigned capacity)
|
||||
{
|
||||
if (aData->capacity != capacity) {
|
||||
aData->bytes = wrealloc(aData->bytes, capacity);
|
||||
aData->capacity = capacity;
|
||||
aData->growth = capacity / 2 > 0 ? capacity / 2 : 1;
|
||||
}
|
||||
if (aData->length > capacity) {
|
||||
aData->length = capacity;
|
||||
}
|
||||
}
|
||||
|
||||
void WMSetDataLength(WMData * aData, unsigned length)
|
||||
{
|
||||
if (length > aData->capacity) {
|
||||
WMSetDataCapacity(aData, length);
|
||||
}
|
||||
if (length > aData->length) {
|
||||
memset((unsigned char *)aData->bytes + aData->length, 0, length - aData->length);
|
||||
}
|
||||
aData->length = length;
|
||||
}
|
||||
|
||||
void WMSetDataFormat(WMData * aData, unsigned format)
|
||||
{
|
||||
aData->format = format;
|
||||
}
|
||||
|
||||
void WMIncreaseDataLengthBy(WMData * aData, unsigned extraLength)
|
||||
{
|
||||
WMSetDataLength(aData, aData->length + extraLength);
|
||||
}
|
||||
|
||||
/* Accessing data */
|
||||
|
||||
const void *WMDataBytes(WMData * aData)
|
||||
{
|
||||
return aData->bytes;
|
||||
}
|
||||
|
||||
void WMGetDataBytes(WMData * aData, void *buffer)
|
||||
{
|
||||
wassertr(aData->length > 0);
|
||||
|
||||
memcpy(buffer, aData->bytes, aData->length);
|
||||
}
|
||||
|
||||
unsigned WMGetDataFormat(WMData * aData)
|
||||
{
|
||||
return aData->format;
|
||||
}
|
||||
|
||||
void WMGetDataBytesWithLength(WMData * aData, void *buffer, unsigned length)
|
||||
{
|
||||
wassertr(aData->length > 0);
|
||||
wassertr(length <= aData->length);
|
||||
|
||||
memcpy(buffer, aData->bytes, length);
|
||||
}
|
||||
|
||||
void WMGetDataBytesWithRange(WMData * aData, void *buffer, WMRange aRange)
|
||||
{
|
||||
wassertr(aRange.position < aData->length);
|
||||
wassertr(aRange.count <= aData->length - aRange.position);
|
||||
|
||||
memcpy(buffer, (unsigned char *)aData->bytes + aRange.position, aRange.count);
|
||||
}
|
||||
|
||||
/* Testing data */
|
||||
|
||||
Bool WMIsDataEqualToData(WMData * aData, WMData * anotherData)
|
||||
{
|
||||
if (aData->length != anotherData->length)
|
||||
return False;
|
||||
else if (!aData->bytes && !anotherData->bytes) /* both are empty */
|
||||
return True;
|
||||
else if (!aData->bytes || !anotherData->bytes) /* one of them is empty */
|
||||
return False;
|
||||
return (memcmp(aData->bytes, anotherData->bytes, aData->length) == 0);
|
||||
}
|
||||
|
||||
unsigned WMGetDataLength(WMData * aData)
|
||||
{
|
||||
return aData->length;
|
||||
}
|
||||
|
||||
/* Adding data */
|
||||
void WMAppendDataBytes(WMData * aData, const void *bytes, unsigned length)
|
||||
{
|
||||
unsigned oldLength = aData->length;
|
||||
unsigned newLength = oldLength + length;
|
||||
|
||||
if (newLength > aData->capacity) {
|
||||
unsigned nextCapacity = aData->capacity + aData->growth;
|
||||
unsigned nextGrowth = aData->capacity ? aData->capacity : 1;
|
||||
|
||||
while (nextCapacity < newLength) {
|
||||
unsigned tmp = nextCapacity + nextGrowth;
|
||||
|
||||
nextGrowth = nextCapacity;
|
||||
nextCapacity = tmp;
|
||||
}
|
||||
WMSetDataCapacity(aData, nextCapacity);
|
||||
aData->growth = nextGrowth;
|
||||
}
|
||||
memcpy((unsigned char *)aData->bytes + oldLength, bytes, length);
|
||||
aData->length = newLength;
|
||||
}
|
||||
|
||||
void WMAppendData(WMData * aData, WMData * anotherData)
|
||||
{
|
||||
if (anotherData->length > 0)
|
||||
WMAppendDataBytes(aData, anotherData->bytes, anotherData->length);
|
||||
}
|
||||
|
||||
/* Modifying data */
|
||||
|
||||
void WMReplaceDataBytesInRange(WMData * aData, WMRange aRange, const void *bytes)
|
||||
{
|
||||
wassertr(aRange.position < aData->length);
|
||||
wassertr(aRange.count <= aData->length - aRange.position);
|
||||
|
||||
memcpy((unsigned char *)aData->bytes + aRange.position, bytes, aRange.count);
|
||||
}
|
||||
|
||||
void WMResetDataBytesInRange(WMData * aData, WMRange aRange)
|
||||
{
|
||||
wassertr(aRange.position < aData->length);
|
||||
wassertr(aRange.count <= aData->length - aRange.position);
|
||||
|
||||
memset((unsigned char *)aData->bytes + aRange.position, 0, aRange.count);
|
||||
}
|
||||
|
||||
void WMSetData(WMData * aData, WMData * anotherData)
|
||||
{
|
||||
unsigned length = anotherData->length;
|
||||
|
||||
WMSetDataCapacity(aData, length);
|
||||
if (length > 0)
|
||||
memcpy(aData->bytes, anotherData->bytes, length);
|
||||
aData->length = length;
|
||||
}
|
||||
|
||||
/* Storing data */
|
||||
196
wutil-rs/src/data.rs
Normal file
196
wutil-rs/src/data.rs
Normal file
@@ -0,0 +1,196 @@
|
||||
//! Self-owning shared data segment.
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Format {
|
||||
Z = 0,
|
||||
E = 8,
|
||||
S = 16,
|
||||
T = 32,
|
||||
}
|
||||
|
||||
/// Reference-counted, self-owned, dynamically sized chunk of bytes.
|
||||
///
|
||||
/// In the original WINGs, this type either owned or borrowed a data buffer and
|
||||
/// had some associated metadata. In Rust, this is little more than a thin
|
||||
/// wrapper around an `Rc<RefCell<Vec<u8>>>`. It is mostly used by proplists,
|
||||
/// and it should be done away with once its dependents have been ported to
|
||||
/// Rust.
|
||||
pub struct Data(Rc<RefCell<Inner>>);
|
||||
|
||||
struct Inner {
|
||||
bytes: Vec<u8>,
|
||||
format: Format,
|
||||
}
|
||||
|
||||
pub mod ffi {
|
||||
use super::{Data, Format, Inner};
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
ffi::{c_int, c_uint, c_void},
|
||||
ptr,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMCreateDataWithCapacity(capacity: c_uint) -> *mut Data {
|
||||
Box::leak(Box::new(Data(Rc::new(RefCell::new(Inner {
|
||||
bytes: Vec::with_capacity(capacity as usize),
|
||||
format: Format::Z,
|
||||
})))))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMCreateDataWithLength(length: c_uint) -> *mut Data {
|
||||
Box::leak(Box::new(Data(Rc::new(RefCell::new(Inner {
|
||||
bytes: vec![0; length as usize],
|
||||
format: Format::Z,
|
||||
})))))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMCreateDataWithBytes(
|
||||
bytes: *const c_void,
|
||||
length: c_uint,
|
||||
) -> *mut Data {
|
||||
let bytes = unsafe { &*ptr::slice_from_raw_parts(bytes.cast::<u8>(), length as usize) };
|
||||
let bytes = Vec::from(bytes);
|
||||
Box::leak(Box::new(Data(Rc::new(RefCell::new(Inner {
|
||||
bytes,
|
||||
format: Format::Z,
|
||||
})))))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMCreateDataWithData(data: *mut Data) -> *mut Data {
|
||||
if data.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let data = unsafe { &*data };
|
||||
Box::leak(Box::new(Data(Rc::new(RefCell::new(Inner {
|
||||
bytes: data.0.borrow().bytes.clone(),
|
||||
format: data.0.borrow().format,
|
||||
})))))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMRetainData(data: *mut Data) -> *mut Data {
|
||||
if data.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let data = unsafe { &*data };
|
||||
Box::leak(Box::new(Data(data.0.clone())))
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMReleaseData(data: *mut Data) {
|
||||
if data.is_null() {
|
||||
return;
|
||||
}
|
||||
let _ = unsafe { ptr::read(data) };
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMDataBytes(data: *mut Data) -> *const c_void {
|
||||
if data.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
unsafe { (*data).0.borrow().bytes.as_ptr().cast::<c_void>() }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMIsDataEqualToData(a: *mut Data, b: *mut Data) -> c_int {
|
||||
if a.is_null() || b.is_null() {
|
||||
return 0;
|
||||
}
|
||||
if ptr::eq(a, b) {
|
||||
return 1;
|
||||
}
|
||||
let a = unsafe { &*a };
|
||||
let b = unsafe { &*b };
|
||||
(a.0.borrow().bytes == b.0.borrow().bytes) as c_int
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMGetDataLength(data: *mut Data) -> c_uint {
|
||||
if data.is_null() {
|
||||
return 0;
|
||||
}
|
||||
unsafe { (*data).0.borrow().bytes.len() as c_uint }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMAppendDataBytes(
|
||||
data: *mut Data,
|
||||
bytes: *const c_void,
|
||||
length: c_uint,
|
||||
) {
|
||||
if data.is_null() || bytes.is_null() || length == 0 {
|
||||
return;
|
||||
}
|
||||
let data = unsafe { &mut *data };
|
||||
let bytes = unsafe { &*ptr::slice_from_raw_parts(bytes.cast::<u8>(), length as usize) };
|
||||
data.0.borrow_mut().bytes.extend_from_slice(bytes);
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMAppendData(data: *mut Data, ext: *mut Data) {
|
||||
if data.is_null() || ext.is_null() {
|
||||
return;
|
||||
}
|
||||
let data = unsafe { &mut *data };
|
||||
let ext = unsafe { &*ext };
|
||||
data.0
|
||||
.borrow_mut()
|
||||
.bytes
|
||||
.extend_from_slice(&ext.0.borrow().bytes);
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMSetData(data: *mut Data, other: *mut Data) {
|
||||
if data.is_null() || other.is_null() {
|
||||
return;
|
||||
}
|
||||
let data = unsafe { &mut *data };
|
||||
let other = unsafe { &*other };
|
||||
data.0
|
||||
.borrow_mut()
|
||||
.bytes
|
||||
.copy_from_slice(&other.0.borrow().bytes);
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMGetDataFormat(data: *mut Data) -> c_uint {
|
||||
if data.is_null() {
|
||||
return 0;
|
||||
}
|
||||
return unsafe {
|
||||
match (*data).0.borrow().format {
|
||||
Format::Z => 0,
|
||||
Format::E => 8,
|
||||
Format::S => 16,
|
||||
Format::T => 32,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn WMSetDataFormat(data: *mut Data, format: c_uint) {
|
||||
if data.is_null() {
|
||||
return;
|
||||
}
|
||||
let format = match format {
|
||||
0 => Format::Z,
|
||||
8 => Format::E,
|
||||
16 => Format::S,
|
||||
32 => Format::T,
|
||||
_ => return,
|
||||
};
|
||||
unsafe {
|
||||
(*data).0.borrow_mut().format = format;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod array;
|
||||
pub mod data;
|
||||
pub mod find_file;
|
||||
pub mod memory;
|
||||
|
||||
Reference in New Issue
Block a user