mpq loader interface cleanup
This commit is contained in:
parent
d136631eb7
commit
089780f619
@ -29,17 +29,17 @@ import (
|
||||
|
||||
type File interface {
|
||||
Read(data []byte) (int, error)
|
||||
GetSize() (int, error)
|
||||
GetSize() int
|
||||
Close() error
|
||||
}
|
||||
|
||||
type Archive interface {
|
||||
OpenFile(path string) (File, error)
|
||||
GetPaths() ([]string, error)
|
||||
GetPaths() []string
|
||||
Close() error
|
||||
}
|
||||
|
||||
func New(path string) (Archive, error) {
|
||||
func NewFromFile(path string) (Archive, error) {
|
||||
cs := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
@ -48,6 +48,11 @@ func New(path string) (Archive, error) {
|
||||
return nil, fmt.Errorf("failed to open archive (%d)", getLastError())
|
||||
}
|
||||
|
||||
if err := a.buildPathMap(); err != nil {
|
||||
a.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
@ -58,12 +63,7 @@ type file struct {
|
||||
}
|
||||
|
||||
func (f *file) Read(data []byte) (int, error) {
|
||||
size, err := f.GetSize()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
bytesRemaining := size - f.offset
|
||||
bytesRemaining := f.size - f.offset
|
||||
if bytesRemaining == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
@ -82,18 +82,8 @@ func (f *file) Read(data []byte) (int, error) {
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func (f *file) GetSize() (int, error) {
|
||||
if f.size != math.MaxUint32 {
|
||||
return f.size, nil
|
||||
}
|
||||
|
||||
size := int(C.SFileGetFileSize(f.handle, nil))
|
||||
if size == -1 {
|
||||
return 0, fmt.Errorf("failed to get file size (%d)", getLastError())
|
||||
}
|
||||
|
||||
f.size = size
|
||||
return size, nil
|
||||
func (f *file) GetSize() int {
|
||||
return f.size
|
||||
}
|
||||
|
||||
func (f *file) Close() error {
|
||||
@ -108,9 +98,19 @@ func (f *file) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *file) buildSize() error {
|
||||
size := int(C.SFileGetFileSize(f.handle, nil))
|
||||
if size == -1 {
|
||||
return fmt.Errorf("failed to get file size (%d)", getLastError())
|
||||
}
|
||||
|
||||
f.size = size
|
||||
return nil
|
||||
}
|
||||
|
||||
type archive struct {
|
||||
handle unsafe.Pointer
|
||||
paths []string
|
||||
paths map[string]string
|
||||
}
|
||||
|
||||
func (a *archive) Close() error {
|
||||
@ -125,7 +125,11 @@ func (a *archive) Close() error {
|
||||
}
|
||||
|
||||
func (a *archive) OpenFile(path string) (File, error) {
|
||||
cs := C.CString(strings.Replace(path, string(os.PathSeparator), "\\", -1))
|
||||
if pathInt, ok := a.paths[path]; ok {
|
||||
path = pathInt
|
||||
}
|
||||
|
||||
cs := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
file := &file{size: math.MaxUint32}
|
||||
@ -133,34 +137,51 @@ func (a *archive) OpenFile(path string) (File, error) {
|
||||
return nil, fmt.Errorf("failed to open file (%d)", getLastError())
|
||||
}
|
||||
|
||||
if err := file.buildSize(); err != nil {
|
||||
file.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (a *archive) GetPaths() ([]string, error) {
|
||||
if len(a.paths) > 0 {
|
||||
return a.paths, nil
|
||||
func (a *archive) GetPaths() []string {
|
||||
var extPaths []string
|
||||
for extPath := range a.paths {
|
||||
extPaths = append(extPaths, extPath)
|
||||
}
|
||||
|
||||
return extPaths
|
||||
}
|
||||
|
||||
func (a *archive) buildPathMap() error {
|
||||
f, err := a.OpenFile("(listfile)")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var buff bytes.Buffer
|
||||
if _, err := io.Copy(&buff, f); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(buff.Bytes()), "\r\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
line = strings.Replace(line, "\\", string(os.PathSeparator), -1)
|
||||
if len(line) > 0 {
|
||||
a.paths = append(a.paths, line)
|
||||
a.paths = make(map[string]string)
|
||||
|
||||
lines := strings.Split(string(buff.Bytes()), "\r\n")
|
||||
for _, line := range lines {
|
||||
pathInt := strings.TrimSpace(line)
|
||||
if len(pathInt) > 0 {
|
||||
pathExt := santizePath(pathInt)
|
||||
a.paths[pathExt] = pathInt
|
||||
}
|
||||
}
|
||||
|
||||
return a.paths, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func santizePath(path string) string {
|
||||
return strings.ToLower(strings.Replace(path, "\\", string(os.PathSeparator), -1))
|
||||
}
|
||||
|
||||
func getLastError() uint {
|
||||
|
@ -6,25 +6,19 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/FooSoft/lazarus/formats/mpq"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
)
|
||||
|
||||
func list(mpqPath, filter string) error {
|
||||
arch, err := mpq.New(mpqPath)
|
||||
arch, err := mpq.NewFromFile(mpqPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer arch.Close()
|
||||
|
||||
resPaths, err := arch.GetPaths()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resPath := range resPaths {
|
||||
for _, resPath := range arch.GetPaths() {
|
||||
match, err := doublestar.Match(filter, resPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -38,19 +32,14 @@ func list(mpqPath, filter string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extract(mpqPath, filter, targetDir string, lowercase bool) error {
|
||||
arch, err := mpq.New(mpqPath)
|
||||
func extract(mpqPath, filter, targetDir string) error {
|
||||
arch, err := mpq.NewFromFile(mpqPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer arch.Close()
|
||||
|
||||
resPaths, err := arch.GetPaths()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resPath := range resPaths {
|
||||
for _, resPath := range arch.GetPaths() {
|
||||
match, err := doublestar.Match(filter, resPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -68,7 +57,7 @@ func extract(mpqPath, filter, targetDir string, lowercase bool) error {
|
||||
}
|
||||
defer resFile.Close()
|
||||
|
||||
sysPath := path.Join(targetDir, strings.ToLower(resPath))
|
||||
sysPath := path.Join(targetDir, resPath)
|
||||
if err := os.MkdirAll(path.Dir(sysPath), 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -93,7 +82,6 @@ func main() {
|
||||
var (
|
||||
filter = flag.String("filter", "**", "wildcard file filter")
|
||||
targetDir = flag.String("target", ".", "target directory")
|
||||
lowercase = flag.Bool("lowercase", true, "extract with lowercase paths")
|
||||
)
|
||||
|
||||
flag.Usage = func() {
|
||||
@ -118,7 +106,7 @@ func main() {
|
||||
}
|
||||
case "extract":
|
||||
for i := 1; i < flag.NArg(); i++ {
|
||||
if err := extract(flag.Arg(i), *filter, *targetDir, *lowercase); err != nil {
|
||||
if err := extract(flag.Arg(i), *filter, *targetDir); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user