You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
numberstation/nsencode.go

134 lines
3.9 KiB

package main
import (
"bufio"
"flag"
"fmt"
"os"
"strings"
"unicode"
)
// Function to encode characters into their respective number pairs
func encodeChar(char rune) int {
// Define the alphabet and numbers with a leading space
alphabet := " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
// Find the index of the character
index := strings.IndexRune(alphabet, char)
if index == -1 {
return -1 // Return -1 if character is not found
}
return index
}
// Function to apply shift and wrap around
func applyShift(value, shift int) int {
shifted := (value + shift) % 37
if shifted < 0 {
shifted += 37
}
return shifted
}
// Function to format the output based on group size and line size
func formatOutput(encoded []int, groupSize int, lineSize int) string {
var output strings.Builder
for _, num := range encoded {
output.WriteString(fmt.Sprintf("%02d", num))
}
finalOutput := output.String()
var groupedOutput strings.Builder
counter := 0
groupCounter := 0
// Check if a group size is provided
if groupSize > 0 {
// Apply grouping and line size limits
for i := 0; i < len(finalOutput); i += groupSize {
if i+groupSize < len(finalOutput) {
groupedOutput.WriteString(finalOutput[i:i+groupSize] + " ")
} else {
groupedOutput.WriteString(finalOutput[i:])
}
counter++
groupCounter++
// Check if we reached the line size
if lineSize > 0 && groupCounter >= lineSize && i+groupSize < len(finalOutput) {
groupedOutput.WriteString("\n")
groupCounter = 0
}
}
} else {
// No group size specified, handle line size by number of characters
for i := 0; i < len(finalOutput); i++ {
groupedOutput.WriteByte(finalOutput[i])
counter++
// Check if we reached the line size
if lineSize > 0 && counter >= lineSize && i+1 < len(finalOutput) {
groupedOutput.WriteString("\n")
counter = 0
}
}
}
return strings.TrimSpace(groupedOutput.String())
}
func main() {
// Define command-line flags
shift := flag.Int("s", 0, "Shift amount for the cipher -- '-s 2' will encode A as 03 instead of 01")
groupSize := flag.Int("g", 0, "Group size for output formatting -- '-g 5' will output numbers in groups of 5")
lineSize := flag.Int("l", 0, "Line size by number of groups -- '-l 4' will split to a new line after every 4th group")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] <<< \"String\"\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s [options] < file.txt\n", os.Args[0])
fmt.Fprintf(os.Stderr, " echo \"string\" | %s [options]\n", os.Args[0])
fmt.Fprintf(os.Stderr, "\nDescription:\n")
fmt.Fprintf(os.Stderr, " A companion program to numberstation, intended to make easy work of making very basic ciphers for numbers station projects.\n")
fmt.Fprintf(os.Stderr, "\nOptions:\n")
flag.PrintDefaults() // Print the default flag help information
fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " %s -s 2 -g 4 <<< \"This is a test\"\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s -s 16 -g 5 -l 4 < file.txt | numberstation -r\n", os.Args[0])
}
flag.Parse()
// Check if there is input from stdin
info, _ := os.Stdin.Stat()
if (info.Mode() & os.ModeCharDevice) != 0 {
flag.Usage()
os.Exit(1)
}
// Read input from stdin
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
var encoded []int
// Encode the input string
for _, char := range input {
if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != ' ' {
continue // Skip characters not in the defined alphabet and numbers
}
encodedValue := encodeChar(unicode.ToUpper(char))
if encodedValue == -1 {
continue // Skip characters not found in the alphabet string
}
shiftedValue := applyShift(encodedValue, *shift)
encoded = append(encoded, shiftedValue)
}
// Format the output
formattedOutput := formatOutput(encoded, *groupSize, *lineSize)
fmt.Println(formattedOutput)
}