docstr: Takes a ciphertext and treats it as a Brainfuck program,
  interpreting it and saving the output as a string to return.
  
  Brainfuck is a very simple, Turing-complete esoteric language.
  Below is a simplified interpreter that attempts to check whether a
  given ciphertext is a brainfuck program that would output a string.
  
  A program that can be "decoded" like this is one that:
      * Does not require user input ("," instruction)
      * Includes at least one putchar instruction (".")
      * Does not contain anything but the main 7 instructions,
          (excluding ",") and whitespace
  
  Details:
      * This implementation wraps the memory pointer for ">" and "<"
      * It is time-limited to 60 seconds, to prevent hangups
      * The program starts with 100 memory cells, chosen arbitrarily
docstr_tok: ["Takes","a","ciphertext","and","treats","it","as","a","Brainfuck","program",",","interpreting","it","and","saving","the","output","as","a","string","to","return",".","Brainfuck","is","a","very","simple",",","Turing-complete","esoteric","language",".","Below","is","a","simplified","interpreter","that","attempts","to","check","whether","a","given","ciphertext","is","a","brainfuck","program","that","would","output","a","string",".","A","program","that","can","be","``","decoded","''","like","this","is","one","that",":","*","Does","not","require","user","input","(","``",",","''","instruction",")","*","Includes","at","least","one","putchar","instruction","(","``",".","''",")","*","Does","not","contain","anything","but","the","main","7","instructions",",","(","excluding","``",",","''",")","and","whitespace","Details",":","*","This","implementation","wraps","the","memory","pointer","for","``",">","''","and","``","<","``","*","It","is","time-limited","to","60","seconds",",","to","prevent","hangups","*","The","program","starts","with","100","memory","cells",",","chosen","arbitrarily"]
code: def decode(self, ctext: T) -> Optional[U]:
      """
      Takes a ciphertext and treats it as a Brainfuck program,
      interpreting it and saving the output as a string to return.
  
      Brainfuck is a very simple, Turing-complete esoteric language.
      Below is a simplified interpreter that attempts to check whether a
      given ciphertext is a brainfuck program that would output a string.
  
      A program that can be "decoded" like this is one that:
          * Does not require user input ("," instruction)
          * Includes at least one putchar instruction (".")
          * Does not contain anything but the main 7 instructions,
              (excluding ",") and whitespace
  
      Details:
          * This implementation wraps the memory pointer for ">" and "<"
          * It is time-limited to 60 seconds, to prevent hangups
          * The program starts with 100 memory cells, chosen arbitrarily
      """
  
      logging.debug("Attempting brainfuck")
  
      result = ""
      memory = [0] * 100
      codeptr, memptr = 0, 0  # Instruction pointer and stack pointer
      timelimit = 60  # The timeout in seconds
  
      bracemap, isbf = self.bracemap_and_check(ctext)
  
      # If it doesn't appear to be valid brainfuck code
      if not isbf:
          logging.debug(
              "Failed to interpret brainfuck due to invalid characters"
          )
          return None
  
      # Get start time
      start = time.time()
  
      while codeptr < len(ctext):
          current = time.time()
  
          # Return none if we've been running for over a minute
          if current - start > timelimit:
              logging.debug(
                  "Failed to interpret brainfuck due to timing out"
              )
              return None
  
          cmd = ctext[codeptr]
  
          if cmd == "+":
              if memory[memptr] < 255:
                  memory[memptr] = memory[memptr] + 1
              else:
                  memory[memptr] = 0
  
          elif cmd == "-":
              if memory[memptr] > 0:
                  memory[memptr] = memory[memptr] - 1
              else:
                  memory[memptr] = 255
  
          elif cmd == ">":
              if memptr == len(memory) - 1:
                  memory.append(0)
              memptr += 1
  
          elif cmd == "<":
              if memptr == 0:
                  memptr = len(memory) - 1
              else:
                  memptr -= 1
  
          # If we're at the beginning of the loop and the memory is 0, exit the loop
          elif cmd == "[" and memory[memptr] == 0:
              codeptr = bracemap[codeptr]
  
          # If we're at the end of the loop and the memory is >0, jmp to the beginning of the loop
          elif cmd == "]" and memory[memptr]:
              codeptr = bracemap[codeptr]
  
          # Store the output as a string instead of printing it out
          elif cmd == ".":
              result += chr(memory[memptr])
  
          codeptr += 1
  
      logging.info(f"Brainfuck successful, returning '{result}'")
      return result
  
file_path: Ciphey/ciphey/basemods/Decoders/brainfuck.py
imports: import re
  import time
  from typing import Dict, Optional, Tuple
  import logging
  from rich.logging import RichHandler
  from ciphey.iface import Config, Decoder, ParamSpec, T, U, WordList, registry
label_desc: Use image node_id 1 for calling the Brainfuck obj's underlying member method code with example usage: obj.decode(ctext) and returns: result, None, None