Re: save and load a 2d array to a file

2022-04-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/19/22 5:12 AM, Stanislav Blinov wrote:

On Tuesday, 19 April 2022 at 06:05:27 UTC, Ali Çehreli wrote:

One quirk of rawWrite and rawRead is that they want slices of objects. 
It is a little awkward when there is just one thing to write and read. 
Uncompiled but something like this:


  int i = 42;
  file.rawWrite(*cast((int[1]*)()));  // Casted to be an array of 1


Yuck :)

```d
file.rawWrite(()[0..1]);
```


Hm... an "asStaticArray" or something similar would be useful for such 
things (and safe too):


```d
ref T[1] asStaticArray(T)(return ref T item) @trusted
{
   return *(cast(T[1]));
}
```

-Steve


Re: save and load a 2d array to a file

2022-04-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 19 April 2022 at 06:05:27 UTC, Ali Çehreli wrote:

One quirk of rawWrite and rawRead is that they want slices of 
objects. It is a little awkward when there is just one thing to 
write and read. Uncompiled but something like this:


  int i = 42;
  file.rawWrite(*cast((int[1]*)()));  // Casted to be an 
array of 1


Yuck :)

```d
file.rawWrite(()[0..1]);
```


Re: save and load a 2d array to a file

2022-04-19 Thread Ali Çehreli via Digitalmars-d-learn

On 4/19/22 01:46, bauss wrote:

> However it should be fairly trivial like:
>
> void rawWriteValue(T)(T value)
> {
>rawWrite(*cast((T[1]*)()));
> }
>
> Or is there some downside to this that I'm missing?

Nonet that I can see. I think I used the following version in actual 
code (adding the missing File parameter as well):


void rawWriteValue(T)(File file, T value)
{
  file.rawWrite(()[0..1]);
}

Ali



Re: save and load a 2d array to a file

2022-04-19 Thread bauss via Digitalmars-d-learn

On Tuesday, 19 April 2022 at 06:05:27 UTC, Ali Çehreli wrote:


  int i = 42;
  file.rawWrite(*cast((int[1]*)()));  // Casted to be an 
array of 1




I assume since we don't have a rawWriteValue, that it's rarely 
needed.


However it should be fairly trivial like:

void rawWriteValue(T)(T value)
{
  rawWrite(*cast((T[1]*)()));
}

Or is there some downside to this that I'm missing?


Re: save and load a 2d array to a file

2022-04-19 Thread Ali Çehreli via Digitalmars-d-learn

On 4/18/22 22:05, Chris Katko wrote:
> D
> struct map_t{
> int data[50][50];
> } map;

Hey! That's C! :)

> //save
> std.file.write("save.map", map.data); // compiles

That serializes the array byte-by-byte.

> //load
> map.data = std.file.read("save.map", map.data.sizeof); // error

And that does the same in reverse and returns void[], which means "just 
bytes".


> main.d(536): Error: cannot implicitly convert expression
> `read("save.map", 2500LU)` of type `void[]` to `ubyte[50][]`

One needs to cast that void[] to the proper type and than assign back. 
However... Instead of that, I like rawWrite and rawRead because both are 
typed and the latter reads on top of existing storage like map.data that 
you have here. So, no extra copy needed.


One quirk of rawWrite and rawRead is that they want slices of objects. 
It is a little awkward when there is just one thing to write and read. 
Uncompiled but something like this:


  int i = 42;
  file.rawWrite(*cast((int[1]*)()));  // Casted to be an array of 1

> I'm guessing here, that internally we've got an array of arrays (which
> means array of pointers),

Not in the case of static arrays: What you have here is nothing 
different from 50x50 ints consecutively in memory.


import std.stdio;
import std.exception;
import std.conv;

struct map_t {
int[50][50] data;
}

void main() {
  map_t map;

  // Some interesting data
  foreach (r, ref row; map.data[]) {
foreach (c, ref element; row[]) {
  element = (1000 * r + c).to!int;
}
  }

  File("save.map", "w").rawWrite(map.data[]);

  map_t other;

  //load
  auto read = File("save.map").rawRead(other.data[]);
  enforce(read.length == map.data.length, "Failed to read all rows of 
the array.");

  enforce(map == other, "The arrays don't match.");
}

Ali



save and load a 2d array to a file

2022-04-18 Thread Chris Katko via Digitalmars-d-learn

D
struct map_t{
int data[50][50];
} map;

//save
std.file.write("save.map", map.data); // compiles

//load
map.data = std.file.read("save.map", map.data.sizeof); // error

main.d(536): Error: cannot implicitly convert expression 
`read("save.map", 2500LU)` of type `void[]` to `ubyte[50][]`



I'm guessing here, that internally we've got an array of arrays 
(which means array of pointers), and D doesn't know how to split 
by one of the axis. So how do I do that? If I know it's exactly 
packed as it was before, can I smash it somehow by direct writing 
a bunch of ubytes?


What is the 'smash' way to do it, and if better, what's the 
elegant way to do it? (In case I need either going forward).


Thanks,
--Chris