Thanks to visit codestin.com
Credit goes to github.com

Skip to content

jgbaldwinbrown/slice

Repository files navigation

Slice

A Go slice-inspired library for easy, memory-safe slice manipulation in C.

Introduction

I'm a big C fan, but I can't help but be impresed by Go's slices. They automatically manage buffer capacity and the starts and ends of arrays such that you don't have to think about memory when you're using one. It's a nice, lightweight abstraction that C can really use. This library fills that niche for C.

Dependencies

make
gcc

Installation

This library is written in portable ANSI C99. It should be possible to build with

make

Usage

Initialization

Each slice contains a pointer to an array, plus the start and end positions of data in the array, the length of the array, and the width of items in the array. A new slice can be initialized as follows:

slice my_slice = new_slice(len, base, item_width)

This generates a new slice with the start and end positions set to 0, and a buffer capacity of len. The base refers to the amount of left padding in the buffer for left appending. The item width refers to the number of bytes used by the array member, and is stored so that the slice can correctly index items in the array. Note that any slice created with new_slice() must be freed with free_slice() to free the underlying dynamic array object.

Adding to the slice

Append new items one at a time to the slice using the following function invocation:

double a = 3.5;
my_slice = append_slice(my_slice, &a)

Or, extend the slice by multiple elements that are contiguous in an array using the following:

double b[] = {3.5, 7,8, 9.3}
my_slice = extend_slice(my_slice, &b[0], 3)

Alternatively, append or extend to the left end of a slice using 'lappend' and 'lextend'

Extracting elements from a slice

Extract all elements from a slice to an array with the slice_extract function:

double a[5];
slice_extract(&a, my_slice)

Sub-slices

Slices may index the dynamic arrays of other slices. These sub-slices are stack-allocated and do not need to be freed. All slices that index the same dynamic array may alter it, but one of the slices must ultimately free it with free_slice().

slice my_sub_slice = sub_slice(my_slice, 1, 3) {

In order to extract just a portion of a slice to an array, use a sub-slice:

double a[5];
slice_extract(&a, sub_slice(my_slice, 3, 5));

Setting elements of a slice

To set the elements of a slice using values from an array, use set_slice_arr():

double a[] = {1.3, 2.4, 3.5};
my_slice = set_slice_arr(my_slice, a, 3);

Or, to set the values of a slice using another slice, use set_slice():

dest_slice = set_slice(dest_slice, source_slice);

Printing a slice

To print the full contents of a slice, simply provide a pointer to the slice and a function pointer for printing an individual element of the slice:

void print_double(void *d) {
    double d2;
    memcpy(&d2, d, sizeof(double));
    printf("%10lg", d2);
}

print_slice(myslice, print_double);

Alternatively, to print the entire contents of a slice, including all indexes and pointers, for debugging, use the following invocation:

introspect_slice(myslice, print_double);

Concatenating slices

To append the contents of a source slice to a destination slice, use concat_slices():

dest_slice = concat_slices(dest_slice, source_slice);

A full example

To make an array of doubles, the following code is acceptable:

#include "slice.h"

int main() {
    double d[] = {1.5, 3.7, 3.8, 9.9, 10.10};
    double d2[10];
    slice my_slice = new_slice(3, 0, sizeof(double));
    
    my_slice = extend_slice(my_slice, d, 5);
    slice my_subslice = sub_slice(my_slice, 1, 3);
    
    print_slice(my_slice, print_double);
    print_slice(my_subslice, print_double);
    
    slice_extract(d2, my_subslice);
    printf("%lg\n", d2[0]);
    
    free_slice(my_slice);
}

This should produce the following output:

	1.5	3.7	3.8	9.9	10.10
	3.7	3.8	9.9
3.8

Creating new slice types

slice.h includes a macro for generating new slice types that hold a specified type. This is the recommended method of using this library, though it is less thoroughly tested right now. The macro NEW_SLICE_TYPE_HEADER() creates all function declarations and the new slice type, while NEW_SLICE_TYPE() defines all of the new functions. Each of these macros takes two arguments. The first argument is the type that the new slice type will hold, and the second is the name to append to all functions associated with this type. These are provided as separate macros so that new slices can be included as header files (see int_slice.h and int_slice.c for an example). An example of a complete program that creates a new slice type for holding doubles, then uses the new type:

#include "slice.h"

NEW_SLICE_TYPE_HEADER(double, double)
NEW_SLICE_TYPE(double, double)

int main() {
    double d[] = {1.5, 3.7, 3.8, 9.9, 10.10};
    double d2;
    double_slice my_slice = double_new_slice(3, 0);
    
    my_slice = double_extend_slice(my_slice, d, 5);
    double_slice my_subslice = double_sub_slice(my_slice, 1, 3);
    
    double_print_slice(my_slice, print_double);
    double_print_slice(my_subslice, print_double);
    
    d2 = slice_extract_double(my_subslice);
    printf("%lg\n", d2);
    
    double_free_slice(my_slice);
}

About

A library for go-like slices in C

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published