github.com/richardwilkes/toolbox@v1.121.0/xio/fs/filename.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package fs
    11  
    12  import (
    13  	"path/filepath"
    14  	"strings"
    15  )
    16  
    17  // SanitizeName sanitizes a file name by replacing invalid characters.
    18  func SanitizeName(name string) string {
    19  	if name == "" {
    20  		return "@0"
    21  	}
    22  	if name == "." {
    23  		return "@1"
    24  	}
    25  	if name == ".." {
    26  		return "@2"
    27  	}
    28  	var buffer strings.Builder
    29  	for _, r := range name {
    30  		switch r {
    31  		case '@':
    32  			buffer.WriteString("@3")
    33  		case '/':
    34  			buffer.WriteString("@4")
    35  		case '\\':
    36  			buffer.WriteString("@5")
    37  		case ':':
    38  			buffer.WriteString("@6")
    39  		default:
    40  			buffer.WriteRune(r)
    41  		}
    42  	}
    43  	return buffer.String()
    44  }
    45  
    46  // UnsanitizeName reverses the effects of a call to SanitizeName.
    47  func UnsanitizeName(name string) string {
    48  	if name == "@0" {
    49  		return ""
    50  	}
    51  	if name == "@1" {
    52  		return "."
    53  	}
    54  	if name == "@2" {
    55  		return ".."
    56  	}
    57  	var buffer strings.Builder
    58  	found := false
    59  	for _, r := range name {
    60  		switch {
    61  		case found:
    62  			switch r {
    63  			case '3':
    64  				buffer.WriteByte('@')
    65  			case '4':
    66  				buffer.WriteByte('/')
    67  			case '5':
    68  				buffer.WriteByte('\\')
    69  			case '6':
    70  				buffer.WriteByte(':')
    71  			default:
    72  				buffer.WriteByte('@')
    73  				buffer.WriteRune(r)
    74  			}
    75  			found = false
    76  		case r == '@':
    77  			found = true
    78  		default:
    79  			buffer.WriteRune(r)
    80  		}
    81  	}
    82  	if found {
    83  		buffer.WriteByte('@')
    84  	}
    85  	return buffer.String()
    86  }
    87  
    88  // BaseName returns the file name without the directory or extension.
    89  func BaseName(path string) string {
    90  	return TrimExtension(filepath.Base(path))
    91  }
    92  
    93  // TrimExtension trims any extension from the path.
    94  func TrimExtension(path string) string {
    95  	return path[:len(path)-len(filepath.Ext(path))]
    96  }