www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Manually allocated structs

reply "Domingo Alvarez Duarte" <mingodad gmail.com> writes:
Hello !

I have the code bellow that I want to manually allocate to use in 
runtime code, because I declared the payload "buf[1]" the 
compiler complains about index out of bounds then I managed to do 
this "*(&tmp.buf + tmp.used++) = c;" instead of 
"tmp.buf[tmp.used++] = c;" as is done usually i "C" there is 
another easy way to achieve the same result in "D" (remember 
manual memory allocation) ?

Cheers !

--------Code

struct lua_char_buffer_st {
     size_t size, used;
     char buf[1];
};

private enum MIN_ALLOC_SIZE = 2048;
private size_t NEW_SIZE(size_t sz) {return 
(((sz/MIN_ALLOC_SIZE)+1)*MIN_ALLOC_SIZE);}

lua_char_buffer_st *lua_new_char_buffer(size_t size){
	lua_char_buffer_st *b;
	size_t n = NEW_SIZE(size);
	b = cast(lua_char_buffer_st*)malloc(lua_char_buffer_st.sizeof + 
n);
	if(b is null) return null;
	b.size = n;
	b.used = 0;
	return b;
}

int lua_char_buffer_add_char(ref LuaMatchState ms, 
lua_char_buffer_st **b, char c){
     lua_char_buffer_st *tmp = *b;
     if(tmp.used+1 >= tmp.size){
         size_t new_size = tmp.size+MIN_ALLOC_SIZE;
         tmp = cast(lua_char_buffer_st*)realloc(tmp, 
lua_char_buffer_st.sizeof + new_size);
         if(tmp is null){
             ms.error = "not enough memory when reallocating";
             return 0;
         }
         *b = tmp;
         tmp.size = new_size;
     }
     *(&tmp.buf + tmp.used++) = c;
     return 1;
}


int lua_char_buffer_add_str(ref LuaMatchState ms, 
lua_char_buffer_st **b, const(char) *str, ptrdiff_t len){
     lua_char_buffer_st *tmp = *b;
     if(len < 0) len = strlen(str);
     if(tmp.used+len >= tmp.size){
         size_t new_size = tmp.size + NEW_SIZE(len);
         tmp = cast(lua_char_buffer_st*)realloc(tmp, 
lua_char_buffer_st.sizeof + new_size);
         if(tmp is null){
             ms.error = "not enough memory when reallocating";
             return 0;
         }
         *b = tmp;
         tmp.size = new_size;
     }
     memcpy(&tmp.buf + tmp.used, str, len);
     tmp.used += len;
     return 1;
}
Jul 27 2014
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
I would do it something like this:

struct test {
	size_t size;

	 property char[] buf() {
		return (_buf.ptr)[0 .. size];
	}
	private char[0] _buf;
}


The buf property returns a slice that uses the size member to 
give you bounds checking, but uses the ptr of the final member in 
the struct to bypass bounds checking on that array.

That way, you can allocate as much memory as you need without 
having to use the naked pointer anywhere outside, getting D to 
help you stay in bounds.
Jul 27 2014
next sibling parent "Domingo Alvarez Duarte" <mingodad gmail.com> writes:
On Sunday, 27 July 2014 at 12:49:01 UTC, Adam D. Ruppe wrote:
 I would do it something like this:

 struct test {
 	size_t size;

 	 property char[] buf() {
 		return (_buf.ptr)[0 .. size];
 	}
 	private char[0] _buf;
 }


 The buf property returns a slice that uses the size member to 
 give you bounds checking, but uses the ptr of the final member 
 in the struct to bypass bounds checking on that array.

 That way, you can allocate as much memory as you need without 
 having to use the naked pointer anywhere outside, getting D to 
 help you stay in bounds.
Yes it did what I was expecting, thank you !
Jul 27 2014
prev sibling parent "Domingo Alvarez Duarte" <mingodad gmail.com> writes:
Hello again !

Anyone knows how to compile with gdc for different versions I 
could not find how gdc implements it if it does ?

The proposed usage of " property char[] buf()" although seems to 
work when compiled with dmd, segfaults when compiled with gdc:

----Code to test

import std.stdio;
import core.stdc.stdlib;

//version(c_style) {
	struct lua_char_buffer_st0 {
	    size_t size, used;
		char[1] buf;
	};
//}

//version(d_style) {
	struct lua_char_buffer_st2 {
	    size_t size, used;
		 property char[] buf() {
			return (_buf.ptr)[0 .. size];
		}
		private char[0] _buf;
	};
//}

//alias lua_char_buffer_st = lua_char_buffer_st0;
alias lua_char_buffer_st = lua_char_buffer_st2;
	
private enum MIN_ALLOC_SIZE = 2048;
private size_t NEW_SIZE(size_t sz) {return 
(((sz/MIN_ALLOC_SIZE)+1)*MIN_ALLOC_SIZE);}

lua_char_buffer_st *lua_realloc_char_buffer(lua_char_buffer_st 
*old, size_t size){
	lua_char_buffer_st *b = old;
	size_t n = NEW_SIZE(size);
	b = cast(lua_char_buffer_st*)realloc(old, 
lua_char_buffer_st.sizeof + n);
	if(b is null) return null;
	b.size = n;
	if(old is null) b.used = 0;
	return b;
}

int lua_char_buffer_add_char(lua_char_buffer_st **b, char c){
     lua_char_buffer_st *tmp = *b;
     if(tmp.used+1 >= tmp.size){
         tmp = lua_realloc_char_buffer(tmp, tmp.used+1);
         if(tmp is null){
             return 0;
         }
         *b = tmp;
     }
     //printf("lua_char_buffer_add_char %p : %p : %d : %d", 
&tmp.buf, tmp.buf.ptr, tmp.size, tmp.used);
     //fflush(stdout);
     //version(c_style)
     //*(&tmp.buf + tmp.used++) = c;
     //version(d_style)
     tmp.buf[tmp.used++] = c;
     return 1;
}

void main()
{
	lua_char_buffer_st *b = lua_realloc_char_buffer(null, 
MIN_ALLOC_SIZE);
	lua_char_buffer_add_char(&b, 'a');
	free(b);
	writeln("Hello !");
}
Jul 27 2014