file.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // acodec
  2. package al
  3. /*
  4. #cgo pkg-config: allegro-5
  5. #cgo CFLAGS: -I/usr/local/include
  6. #cgo linux LDFLAGS: -lc_nonshared
  7. #include <stdlib.h>
  8. #include <allegro5/allegro.h>
  9. #include <allegro5/file.h>
  10. #include "helpers.h"
  11. #include "callbacks.h"
  12. */
  13. import "C"
  14. import "errors"
  15. import "runtime"
  16. import "unsafe"
  17. // Allegro's own file for cross platform and physfs reasons.
  18. type File struct {
  19. handle *C.ALLEGRO_FILE
  20. }
  21. // Closes the Allegro file
  22. func (self *File) Close() {
  23. if self.handle != nil {
  24. C.al_fclose(self.handle)
  25. }
  26. self.handle = nil
  27. }
  28. // Returns the low level handle of the file
  29. func (self *File) toC() * C.ALLEGRO_FILE {
  30. return self.handle
  31. }
  32. // Wraps an ALLEGRO_FILE into a File
  33. func wrapFileRaw(file *C.ALLEGRO_FILE) *File {
  34. if file == nil {
  35. return nil
  36. }
  37. return &File{file}
  38. }
  39. // Opens an Allegro File
  40. func openFile(filename, mode string) *C.ALLEGRO_FILE {
  41. cfilename := cstr(filename)
  42. defer cstrFree(cfilename)
  43. cmode := cstr(mode)
  44. defer cstrFree(cmode)
  45. return C.al_fopen(cfilename, cmode)
  46. }
  47. // Sets up a finalizer for this File that calls Close()
  48. func (self *File) SetCloseFinalizer() *File {
  49. if self != nil {
  50. runtime.SetFinalizer(self, func(me *File) { me.Close() })
  51. }
  52. return self
  53. }
  54. // Wraps a file and sets up a finalizer that calls Destroy()
  55. func wrapFile(data *C.ALLEGRO_FILE) *File {
  56. self := wrapFileRaw(data)
  57. return self.SetCloseFinalizer()
  58. }
  59. // Opens a file with no finalizer set
  60. func OpenFileRaw(filename, mode string) *File {
  61. self := openFile(filename, mode)
  62. return wrapFileRaw(self)
  63. }
  64. // Opens a file with a Close finalizer set
  65. func OpenFile(filename, mode string) *File {
  66. self := OpenFileRaw(filename, mode)
  67. return self.SetCloseFinalizer()
  68. }
  69. /* File interface is as good as useless in GO, too many
  70. * callbacks. */
  71. type Seek C.enum_ALLEGRO_SEEK
  72. const (
  73. SEEK_SET = Seek(C.ALLEGRO_SEEK_SET)
  74. SEEK_CUR = Seek(C.ALLEGRO_SEEK_CUR)
  75. SEEK_END = Seek(C.ALLEGRO_SEEK_END)
  76. )
  77. func (f * File) Read(p []byte) (n int, err error) {
  78. err = nil
  79. size := C.al_fread(f.toC(), unsafe.Pointer(&p[0]), C.size_t(len(p)))
  80. n = int(size)
  81. erri := C.al_ferror(f.toC())
  82. if erri != 0 {
  83. mesg := C.GoString(C.al_ferrmsg(f.toC()))
  84. err = errors.New("Could not read file: " + mesg)
  85. }
  86. return n, err
  87. }
  88. /* No Allegro File IO (yet) since that is redundant with Go's std libs.
  89. * Likeswise I'm skipping fixed point math and
  90. * the FS entry.
  91. */