file.go 2.4 KB

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