mirror of
https://github.com/golang/go
synced 2024-11-22 09:14:40 -07:00
mime: range glob expansions in type_unix.go
This commit is contained in:
parent
176b63e711
commit
b41e88d296
@ -8,6 +8,7 @@ package mime
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
@ -49,7 +50,8 @@ func loadMimeGlobsFile(filename string) error {
|
||||
}
|
||||
|
||||
extension := fields[2][1:]
|
||||
if strings.ContainsAny(extension, "?*[") {
|
||||
switch {
|
||||
case strings.ContainsAny(extension, "?*"):
|
||||
// Not a bare extension, but a glob. Ignore for now:
|
||||
// - we do not have an implementation for this glob
|
||||
// syntax (translation to path/filepath.Match could
|
||||
@ -60,7 +62,15 @@ func loadMimeGlobsFile(filename string) error {
|
||||
// - trying to match glob metacharacters literally is
|
||||
// not useful
|
||||
continue
|
||||
case strings.Contains(extension, "["):
|
||||
if extensions, ok := expand(extension); ok {
|
||||
for i := range extensions {
|
||||
setExtensionType(extensions[i], fields[1])
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := mimeTypes.Load(extension); ok {
|
||||
// We've already seen this extension.
|
||||
// The file is in weight order, so we keep
|
||||
@ -124,3 +134,78 @@ func initMimeForTests() map[string]string {
|
||||
".png": "image/png",
|
||||
}
|
||||
}
|
||||
|
||||
func expand(glob string) ([]string, bool) {
|
||||
runes := []rune(glob)
|
||||
resultSize := 1
|
||||
stringSize := 0
|
||||
|
||||
countLoop:
|
||||
for i := 0; i < len(runes); i++ {
|
||||
switch runes[i] {
|
||||
case '[':
|
||||
for j := i + 1; j < len(runes); j++ {
|
||||
if runes[j] == ']' {
|
||||
i = j
|
||||
continue countLoop
|
||||
}
|
||||
if runes[j+1] == '-' {
|
||||
if j+2 >= len(runes) {
|
||||
return nil, false
|
||||
}
|
||||
resultSize *= int(runes[j+2]-runes[j]) + 1
|
||||
stringSize++
|
||||
j += 2
|
||||
continue
|
||||
}
|
||||
resultSize++
|
||||
stringSize++
|
||||
}
|
||||
default:
|
||||
stringSize++
|
||||
}
|
||||
}
|
||||
|
||||
buffers := make([]bytes.Buffer, resultSize, resultSize)
|
||||
for i := range buffers {
|
||||
buffers[i].Grow(stringSize)
|
||||
}
|
||||
|
||||
for i := 0; i < len(runes); i++ {
|
||||
switch runes[i] {
|
||||
case '[':
|
||||
var expanded []rune
|
||||
for j := i + 1; j < len(runes); j++ {
|
||||
if runes[j] == ']' {
|
||||
i = j
|
||||
break
|
||||
}
|
||||
if runes[j+1] == '-' {
|
||||
for k := runes[j]; k <= runes[j+2]; k++ {
|
||||
expanded = append(expanded, k)
|
||||
}
|
||||
j += 2
|
||||
continue
|
||||
}
|
||||
expanded = append(expanded, runes[j])
|
||||
}
|
||||
|
||||
for j, k := 0, 0; j < resultSize; j, k = j+1, (k+1)%len(expanded) {
|
||||
buffers[j].WriteRune(expanded[k])
|
||||
}
|
||||
|
||||
default:
|
||||
for j := 0; j < resultSize; j++ {
|
||||
buffers[j].WriteRune(runes[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]string, 0, resultSize)
|
||||
for i := 0; i < resultSize; i++ {
|
||||
result = append(result, buffers[i].String())
|
||||
}
|
||||
|
||||
return result, true
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,9 @@ func TestTypeByExtensionUNIX(t *testing.T) {
|
||||
".foo?ar": "",
|
||||
".foo*r": "",
|
||||
".foo[1-3]": "",
|
||||
".foo1": "example/glob-range",
|
||||
".foo2": "example/glob-range",
|
||||
".foo3": "example/glob-range",
|
||||
}
|
||||
|
||||
for ext, want := range typeTests {
|
||||
@ -41,3 +44,15 @@ func TestTypeByExtensionUNIX(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMimeExtension(t *testing.T) {
|
||||
initMimeUnixTest(t)
|
||||
exts, _ := ExtensionsByType("example/glob-range")
|
||||
expected := []string{".foo1", ".foo2", ".foo3"}
|
||||
|
||||
for i := range exts {
|
||||
if exts[i] != expected[i] {
|
||||
t.Errorf("Want %q, got %q", expected[i], exts[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user