Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RawArray needs a slicing operation #5701

Closed
gau-veldt opened this issue Jul 14, 2016 · 11 comments
Closed

RawArray needs a slicing operation #5701

gau-veldt opened this issue Jul 14, 2016 · 11 comments

Comments

@gau-veldt
Copy link
Contributor

Operating system or device - Godot version:
Godot v2.1.beta

Issue description (what happened, and what was expected):
RawArray supports adding chunks onto the end but missed an operation to obtain a copied slice of a larger RawArray to a new (smaller) RawArray. Of course this could be done in a loop but things like that may be a bit inefficient doing in script, especially for larger RawArray's. C++ optimized assembly FTW.

Proposed prototype (-1 means end of the array):

RawArray RawArray.slice(start,end=-1)

Copies a slice of the original RawArray and returns a new RawArray containing the subsection, from start to end (or -1 to slice to the end).

# example to use proposed RawArray.slice
func skipN(origRaw,N):
    # returns new RawArray with first N bytes of original RawArray skipped
   return origRaw.slice(N)
@gau-veldt
Copy link
Contributor Author

gau-veldt commented Jul 14, 2016

If adding a bind isn't too tricky a process I could try to add this to a fork and go through the PR process.
It would be nice if there was way to make these slices without copying but I see peril in doing so.

Edit: It looks tedious. Trying a grep on the sources for RawArray didn't find any of the implementation functions. Must be using templates.

@bojidar-bg
Copy link
Contributor

@gau-veldt I think it was named ByteArray on the C++ side (or it is part of DVector)

@gau-veldt
Copy link
Contributor Author

I need more information about where I should be looking in the sources to add this method to RawArray since I can't even find the implementations of the currently defined methods E.g.: RawArray.append()

@vnen
Copy link
Member

vnen commented Jul 17, 2016

  1. RawArray is called ByteArray in C++ (source). (this is problematic and it'll be normalized in 3.0 when we break compatibility).
  2. ByteArray is just DVector<uint8_t> (source). Other *Array types are also DVectors.
  3. If you want to add a function you need to add it to DVector. Which means it can be available (if bound) to any of the *Array types.
  4. Those are bound in core/variant_call.cpp here and here (you need to add it in both places, as they do different things).

That should be enough to start.

@gau-veldt
Copy link
Contributor Author

gau-veldt commented Jul 17, 2016

Actually I think it's already there since I've seen ByteArray.subarray in the code which is basically what a .slice() method would be doing. The only problem is subarray() returns the same array (at different pointers) this is likely not safe to use as-is in a naive bind for GDScript since the following code would cause trouble:

a1=RawArray([1,2,3,5,6,7,8,9,10])
a2=RawArray.slice(2,4)   # [3,5,6]  implemented as a bind to ByteArray.subarray()
a2.insert(1,[4])  # a2 wants to be [3,4,5,6]
# a1 has now been modified
# and probably contains (1,2,3,4,5,6,8,9,10)
# worse a2[0] might be attempted for realloc on insert (causing a free a2[0]) causing crash

For GDScript it is likely required to make a copy of the subarray to be safe, requiring additional code for the GDScript implementation specifically, not the DVector template.

@gau-veldt
Copy link
Contributor Author

gau-veldt commented Jul 17, 2016

okay I do have to make my owqn subarray method on DVector since the subarray I spotted in the code was actually from the java portion,

@gau-veldt
Copy link
Contributor Author

Hopefully this won't be too ugly an implementation:

    DVector<T> subarray(int p_from, int p_to) {

            if (p_from<0 || p_from>=size()) {
                    T& aux=*((T*)0); //nullreturn
                    ERR_FAIL_COND_V(p_from<0 || p_from>=size(),aux)
            }
            if (p_to<0 || p_to>=size()) {
                    T& aux=*((T*)0); //nullreturn
                    ERR_FAIL_COND_V(p_to<0 || p_to>=size(),aux)
            }

            DVector<T> slice;
            int span=1 + p_to - p_from;
            slice.resize(span);
            Read r = read();
            Write w = slice.write();
            for (int i=0; i<span; ++i) {
                    w[i] = r[p_from+i];
            }

            return slice;
    }

@gau-veldt
Copy link
Contributor Author

gau-veldt commented Jul 17, 2016

If this is OK I can then attempt to do the bind for RawArray.

PS: I've kept the name from ByteArray's subarray method in the java glue. From GDScript it probably looks better if exposed to scripts via binding as slice (on account that GDScript borrows from Python and Python calls this very operation slicing).

@gau-veldt
Copy link
Contributor Author

It's in my github fork guess I need to do a PR and reference this issue. PR is #5765

@gau-veldt
Copy link
Contributor Author

gau-veldt commented Jul 18, 2016

The PR includes documentation of the method in classes.xml as well as handling of -1 to mean 'last element'.

@gau-veldt
Copy link
Contributor Author

I think the merging of #5879 closes this one.

@akien-mga akien-mga added this to the 2.2 milestone Sep 18, 2016
@akien-mga akien-mga modified the milestones: 2.2, 3.0 Dec 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants