diff --git a/File.c b/File.c index e07bc466..ce4f8387 100644 --- a/File.c +++ b/File.c @@ -1,3 +1,4 @@ +#include #include "general.h" #include "THFile.h" #include "luaT.h" @@ -155,6 +156,47 @@ static int torch_File_writeString(lua_State *L) return 1; } +static int torch_File_readPointer(lua_State *L) +{ + THFile *self = luaT_checkudata(L, 1, "torch.File"); + int narg = lua_gettop(L); + + if(narg == 1) + { + intptr_t value; + size_t size = THFile_readPointerRaw(self, &value); + if(size < 1) + { + luaL_error(L, "can not read pointer"); + return 0; + } + lua_pushinteger(L, value); + return 1; + } + + luaL_error(L, "nothing expected"); + return 0; +} + +static int torch_File_writePointer(lua_State *L) +{ + THFile *self = luaT_checkudata(L, 1, "torch.File"); + int narg = lua_gettop(L); + + if(narg == 2) + { + if(lua_isnumber(L, 2)) + { + intptr_t value = lua_tointeger(L, 2); + THFile_writePointerRaw(self, value); + return 1; + } + } + + luaL_error(L, "number expected"); + return 0; +} + static const struct luaL_Reg torch_File__ [] = { {"isQuiet", torch_File_isQuiet}, {"isReadable", torch_File_isReadable}, @@ -180,6 +222,7 @@ static const struct luaL_Reg torch_File__ [] = { {"readFloat", torch_File_readFloat}, {"readDouble", torch_File_readDouble}, {"readString", torch_File_readString}, + {"readPointer", torch_File_readPointer}, {"writeByte", torch_File_writeByte}, {"writeChar", torch_File_writeChar}, @@ -189,6 +232,7 @@ static const struct luaL_Reg torch_File__ [] = { {"writeFloat", torch_File_writeFloat}, {"writeDouble", torch_File_writeDouble}, {"writeString", torch_File_writeString}, + {"writePointer", torch_File_writePointer}, {"synchronize", torch_File_synchronize}, {"seek", torch_File_seek}, diff --git a/doc/file.md b/doc/file.md index c4aa742c..2f9677bb 100644 --- a/doc/file.md +++ b/doc/file.md @@ -68,6 +68,9 @@ If a `Storage` is given, the method will attempt to read a number of elements equals to the size of the given storage, and fill up the storage with these elements. The number of elements actually read is returned. +A convenient method exists to read one pointer as a integer: `[integer] readPointer()`. It reads +in `"%p"` format if `File` is of ascii encoding. This method does not support `n` or `Storage`. + In case of read error, these methods will call the `Lua` error function using the default [pedantic](#torch.File.pedantic) option, or stay quiet with the [quiet](#torch.File.quiet) option. In the latter case, one can check if an error occurred with @@ -109,6 +112,9 @@ in the storage. These methods return the number of elements actually written. +A convenient method exists to write one pointer: `writePointer(integer)`. It writes +in `"%p"` format if `File` is of ascii encoding. This method does not support `Storage`. + In case of write error, these methods will call the `Lua` error function using the default [pedantic](#torch.File.pedantic) option, or stay quiet with the [quiet](#torch.File.quiet) option. In the latter case, one can check if an error occurred with @@ -196,14 +202,14 @@ in the file, as only a reference to the original will be written. See ### [string] readString(format) ### -If `format` starts with ''"*l"` then returns the next line in the `File''. The end-of-line character is skipped. +If `format` starts with `"*l"` then returns the next line in the `File`. The end-of-line character is skipped. -If `format` starts with ''"*a"` then returns all the remaining contents of the `File''. +If `format` starts with `"*a"` then returns all the remaining contents of the `File`. If no data is available, then an error is raised, except if `File` is in [quiet()](#torch.File.quiet) mode where it then returns an empty string `''` and after that you'll be able to see that last reading failed due to end of file with your_file:[hasError()](#torch.File.hasError). -Because Torch is more precise on number typing, the `Lua` format ''"*n"'' is not supported: +Because Torch is more precise on number typing, the `Lua` format `"*n"` is not supported: instead use one of the [number read methods](#torch.File.read). diff --git a/lib/TH/THDiskFile.c b/lib/TH/THDiskFile.c index 01b19513..a3742c00 100644 --- a/lib/TH/THDiskFile.c +++ b/lib/TH/THDiskFile.c @@ -360,6 +360,10 @@ READ_WRITE_METHODS(double, Double, int ret = fscanf(dfself->handle, "%lg", &data[i]); if(ret <= 0) break; else nread++, int ret = fprintf(dfself->handle, "%.17g", data[i]); if(ret <= 0) break; else nwrite++) +READ_WRITE_METHODS(intptr_t, Pointer, + int ret = fscanf(dfself->handle, "%p", (void **)&data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%p", (void *)data[i]); if(ret <= 0) break; else nwrite++) + /* For Long we need to rewrite everything, because of the special management of longSize */ static size_t THDiskFile_readLong(THFile *self, long *data, size_t n) @@ -620,6 +624,7 @@ THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet) THDiskFile_readDouble, THDiskFile_readHalf, THDiskFile_readString, + THDiskFile_readPointer, THDiskFile_writeByte, THDiskFile_writeChar, @@ -630,6 +635,7 @@ THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet) THDiskFile_writeDouble, THDiskFile_writeHalf, THDiskFile_writeString, + THDiskFile_writePointer, THDiskFile_synchronize, THDiskFile_seek, @@ -734,6 +740,7 @@ THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet) THDiskFile_readDouble, THDiskFile_readHalf, THDiskFile_readString, + THDiskFile_readPointer, THDiskFile_writeByte, THDiskFile_writeChar, @@ -744,6 +751,7 @@ THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet) THDiskFile_writeDouble, THDiskFile_writeHalf, THDiskFile_writeString, + THDiskFile_writePointer, THDiskFile_synchronize, THDiskFile_seek, diff --git a/lib/TH/THFile.c b/lib/TH/THFile.c index 3717b7b5..df880647 100644 --- a/lib/TH/THFile.c +++ b/lib/TH/THFile.c @@ -31,6 +31,16 @@ size_t THFile_writeStringRaw(THFile *self, const char *str, size_t size) return self->vtable->writeString(self, str, size); } +size_t THFile_readPointerRaw(THFile *self, intptr_t *data) +{ + return self->vtable->readPointer(self, data, 1); +} + +size_t THFile_writePointerRaw(THFile *self, intptr_t data) +{ + return self->vtable->writePointer(self, &data, 1); +} + void THFile_synchronize(THFile *self) { self->vtable->synchronize(self); diff --git a/lib/TH/THFile.h b/lib/TH/THFile.h index e097bdf3..1f45a768 100644 --- a/lib/TH/THFile.h +++ b/lib/TH/THFile.h @@ -1,6 +1,7 @@ #ifndef TH_FILE_INC #define TH_FILE_INC +#include #include "THStorage.h" typedef struct THFile__ THFile; @@ -64,6 +65,7 @@ TH_API size_t THFile_readLongRaw(THFile *self, long *data, size_t n); TH_API size_t THFile_readFloatRaw(THFile *self, float *data, size_t n); TH_API size_t THFile_readDoubleRaw(THFile *self, double *data, size_t n); TH_API size_t THFile_readStringRaw(THFile *self, const char *format, char **str_); /* you must deallocate str_ */ +TH_API size_t THFile_readPointerRaw(THFile *self, intptr_t *data); TH_API size_t THFile_writeByteRaw(THFile *self, unsigned char *data, size_t n); TH_API size_t THFile_writeCharRaw(THFile *self, char *data, size_t n); @@ -73,6 +75,7 @@ TH_API size_t THFile_writeLongRaw(THFile *self, long *data, size_t n); TH_API size_t THFile_writeFloatRaw(THFile *self, float *data, size_t n); TH_API size_t THFile_writeDoubleRaw(THFile *self, double *data, size_t n); TH_API size_t THFile_writeStringRaw(THFile *self, const char *str, size_t size); +TH_API size_t THFile_writePointerRaw(THFile *self, intptr_t data); TH_API THHalf THFile_readHalfScalar(THFile *self); TH_API void THFile_writeHalfScalar(THFile *self, THHalf scalar); diff --git a/lib/TH/THFilePrivate.h b/lib/TH/THFilePrivate.h index 55169c3b..da66db93 100644 --- a/lib/TH/THFilePrivate.h +++ b/lib/TH/THFilePrivate.h @@ -2,6 +2,7 @@ #include "THHalf.h" +#include struct THFile__ { @@ -30,6 +31,7 @@ struct THFileVTable size_t (*readDouble)(THFile *self, double *data, size_t n); size_t (*readHalf)(THFile *self, THHalf *data, size_t n); size_t (*readString)(THFile *self, const char *format, char **str_); + size_t (*readPointer)(THFile *self, intptr_t *data, size_t n); size_t (*writeByte)(THFile *self, unsigned char *data, size_t n); size_t (*writeChar)(THFile *self, char *data, size_t n); @@ -40,6 +42,7 @@ struct THFileVTable size_t (*writeDouble)(THFile *self, double *data, size_t n); size_t (*writeHalf)(THFile *self, THHalf *data, size_t n); size_t (*writeString)(THFile *self, const char *str, size_t size); + size_t (*writePointer)(THFile *self, intptr_t *data, size_t n); void (*synchronize)(THFile *self); void (*seek)(THFile *self, size_t position); diff --git a/lib/TH/THMemoryFile.c b/lib/TH/THMemoryFile.c index ecce6e1b..13bd8e0c 100644 --- a/lib/TH/THMemoryFile.c +++ b/lib/TH/THMemoryFile.c @@ -349,6 +349,11 @@ READ_WRITE_METHODS(double, Double, nByteWritten = snprintf(mfself->storage->data+mfself->position, mfself->storage->size-mfself->position, "%.17g", data[i]), 1) +READ_WRITE_METHODS(intptr_t, Pointer, + int nByteRead_; int ret = sscanf(mfself->storage->data+mfself->position, "%p%n", (void **)&data[i], &nByteRead_); nByteRead = nByteRead_; if(ret <= 0) break; else nread++, + nByteWritten = snprintf(mfself->storage->data+mfself->position, mfself->storage->size-mfself->position, "%p", (void *)data[i]), + 1) + int THDiskFile_isLittleEndianCPU(void); static size_t THMemoryFile_readLong(THFile *self, long *data, size_t n) @@ -625,6 +630,7 @@ THFile *THMemoryFile_newWithStorage(THCharStorage *storage, const char *mode) THMemoryFile_readDouble, THMemoryFile_readHalf, THMemoryFile_readString, + THMemoryFile_readPointer, THMemoryFile_writeByte, THMemoryFile_writeChar, @@ -635,6 +641,7 @@ THFile *THMemoryFile_newWithStorage(THCharStorage *storage, const char *mode) THMemoryFile_writeDouble, THMemoryFile_writeHalf, THMemoryFile_writeString, + THMemoryFile_writePointer, THMemoryFile_synchronize, THMemoryFile_seek, diff --git a/test/test_sharedmem.lua b/test/test_sharedmem.lua index 1230e591..2fa8732e 100644 --- a/test/test_sharedmem.lua +++ b/test/test_sharedmem.lua @@ -88,5 +88,26 @@ function tests.testSharing() removeShmFile(shmFileName) end +function tests.readWritePointer() + local tensor = torch.rand(2,3) + local addr1 = torch.pointer(tensor) + tester:assert(type(addr1)=='number') + + local f = torch.MemoryFile() + f:binary() + f:writePointer(addr1) + f:seek(1) + local addr2 = f:readPointer() + f:close() + tester:assert(addr1 == addr2) + + local f = torch.MemoryFile() + f:writePointer(addr1) + f:seek(1) + local addr2 = f:readPointer() + f:close() + tester:assert(addr1 == addr2) +end + tester:add(tests) tester:run()