Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Junkstring functions
- CREDITS:
- + Original Plugin (https://www.roblox.com/library/2744793551/)
- by Autterfly (https://www.roblox.com/users/70540486/profile/)
- + Moonsec junkstring functions by yours truly
- Don't erase the credits. It's uncool. :(
- To look over documentation, ctrl + f "Noted Function 1"
- Note:
- Doesn't include some escape sequences in longstrings
- Updates (M/D/Y):
- 8/10/21
- + PSU junkstring
- 8/10/21 >
- + Moonsec junkstring functions
- --]]
- -- Variables
- -- tables
- local JunkstringFunctions = {}
- local JunkstringOptions = {}
- -- noted
- local WhiteChars,CharacterForEscape,AllIdentStartChars,AllIdentChars,Keywords,Digits,HexDigits,
- BinaryDigits,EqualSymbols,CompoundAssignments,Symbols
- = unpack{};
- -- functions
- ----------------------------------------------------------------------------------------------------
- -- > Autterfly
- ----------------------------------------------------------------------------------------------------
- local function CreateLuaTokenStream(text)
- -- Tracking for the current position in the buffer, and
- -- the current line / character we are on.
- local p = 1
- -- Output buffer for tokens
- local tokenBuffer = {}
- -- Get a character, or '' if at eof
- local function look(n)
- n = p + (n or 0)
- return text:sub(n, n)
- end
- local function get()
- local c = text:sub(p, p)
- p = p + 1
- return c
- end
- -- Error
- local olderr = error
- local function error(str)
- local q = 1
- local line = 1
- local char = 1
- while q <= p do
- if text:sub(q, q) == '\n' then
- line = line + 1
- char = 1
- else
- char = char + 1
- end
- q = q + 1
- end
- for _, token in pairs(tokenBuffer) do
- print(token.Type.."<"..token.Source..">")
- end
- olderr("file<"..line..":"..char..">: "..str)
- end
- -- Consume a long data with equals count of `eqcount'
- local function longdata(eqcount)
- while true do
- local c = get()
- if c == '' then
- error("Unfinished long string.")
- elseif c == ']' then
- local done = true -- Until contested
- for _ = 1, eqcount do
- if look() == '=' then
- p = p + 1
- else
- done = false
- break
- end
- end
- if done and get() == ']' then
- return
- end
- end
- end
- end
- -- Get the opening part for a long data `[` `=`* `[`
- -- Precondition: The first `[` has been consumed
- -- Return: nil or the equals count
- local function getopen()
- local startp = p
- while look() == '=' do
- p = p + 1
- end
- if look() == '[' then
- p = p + 1
- return p - startp - 1
- else
- p = startp
- return nil
- end
- end
- -- Add token
- local whiteStart = 1
- local tokenStart = 1
- local function token(type)
- local tk = {
- Type = type;
- LeadingWhite = text:sub(whiteStart, tokenStart-1);
- Source = text:sub(tokenStart, p-1);
- }
- table.insert(tokenBuffer, tk)
- whiteStart = p
- tokenStart = p
- return tk
- end
- -- Parse tokens loop
- while true do
- -- Mark the whitespace start
- whiteStart = p
- -- Get the leading whitespace + comments
- while true do
- local c = look()
- if c == '' then
- break
- elseif c == '-' then
- if look(1) == '-' then
- p = p + 2
- -- Consume comment body
- if look() == '[' then
- p = p + 1
- local eqcount = getopen()
- if eqcount then
- -- Long comment body
- longdata(eqcount)
- else
- -- Normal comment body
- while true do
- local c2 = get()
- if c2 == '' or c2 == '\n' then
- break
- end
- end
- end
- else
- -- Normal comment body
- while true do
- local c2 = get()
- if c2 == '' or c2 == '\n' then
- break
- end
- end
- end
- else
- break
- end
- elseif WhiteChars[c] then
- p = p + 1
- else
- break
- end
- end
- -- local leadingWhite = text:sub(whiteStart, p-1) -- unused(?)
- -- Mark the token start
- tokenStart = p
- -- Switch on token type
- local c1 = get()
- if c1 == '' then
- -- End of file
- token('Eof')
- break
- elseif c1 == '\'' or c1 == '\"' then
- -- String constant
- while true do
- local c2 = get()
- if c2 == '\\' then
- local c3 = get()
- if tonumber(c3) or c3:lower()=='x' then -- Reru fix
- for _ = 1, 2 do
- c3 = c3 .. look()
- local num = tonumber('0'..c3)
- if tonumber(c3)or num then
- get()
- if (tonumber(c3) or num) > 255 then
- error("Non representable character escape `" .. c3 .. "`.")
- end
- else
- break
- end
- end
- else
- local esc = CharacterForEscape[c3]
- if not esc then
- error("Invalid Escape Sequence `"..c3.."`.")
- end
- end
- elseif c2 == c1 then
- break
- end
- end
- token('String')
- elseif AllIdentStartChars[c1] then
- -- Ident or Keyword
- while AllIdentChars[look()] do
- p = p + 1
- end
- if Keywords[text:sub(tokenStart, p-1)] then
- token('Keyword')
- else
- token('Ident')
- end
- elseif Digits[c1] or (c1 == '.' and Digits[look()]) then
- -- Number
- local HexLuaUNumber = text:match('[_]+[xX][%x_]+',p)
- local TouchedX = look():lower() == 'x'
- local BinLuaUNumber = text:match('[_]+[bB][01_]+',p)
- local TouchedB = look():lower() == 'b'
- -- note: may need to do this better, code below look similar
- if c1 == '0' and (TouchedX or HexLuaUNumber) then
- p = p + 1
- -- Hex number
- while HexDigits[look()]or
- look()=='_'or
- (not TouchedX and look():lower()=='x')do
- if(not TouchedX and look():lower()=='x')then
- TouchedX = true
- end
- p = p + 1
- end
- elseif c1 == '0' and (TouchedB or BinLuaUNumber) then
- p = p + 1
- -- bin number
- while BinaryDigits[look()]or
- look()=='_'or
- (not TouchedB and look():lower()=='b')do
- if(not TouchedB and look():lower()=='b')then
- TouchedB = true
- end
- p = p + 1
- end
- else
- -- Normal Number + weird luau number with underscore
- while Digits[look()]or look()=='_'do
- p = p + 1
- end
- if look() == '.' then
- -- With decimal point
- p = p + 1
- while Digits[look()]or look()=='_' do
- p = p + 1
- end
- end
- if look():lower() == 'e' then
- -- With exponent
- p = p + 1
- if look() == '-' then
- p = p + 1
- end
- while Digits[look()]or look()=='_' do
- p = p + 1
- end
- end
- end
- token('Number')
- elseif c1 == '[' then
- -- '[' Symbol or Long String
- local eqCount = getopen()
- if eqCount then
- -- Long string
- longdata(eqCount)
- token('String')
- else
- -- Symbol
- token('Symbol')
- end
- elseif c1 == '.' then
- -- Greedily consume up to 3 `.` for . / .. / ... tokens + compound operator ..=
- if look() == '.' then
- get()
- if ({
- ['.'] = true;
- ['='] = true
- })[look()]then
- get()
- end
- end
- token('Symbol')
- elseif EqualSymbols[c1] then
- if look() == '=' then
- p = p + 1
- end
- token('Symbol')
- elseif CompoundAssignments[c1 .. look()] then
- p = p + 1
- token('Symbol')
- elseif Symbols[c1] then
- token('Symbol')
- else
- error("Bad symbol `"..c1.."` in source.")
- end
- end
- return tokenBuffer
- end
- ----------------------------------------------------------------------------------------------------
- -- > Yours truly
- ----------------------------------------------------------------------------------------------------
- -- 1l
- function FlipTable(t)local a = {}for i,v in next,t do a[v] = i end return a end
- function lookifycharactersfromstring(a)return FlipTable(a:split'')end
- function TableRandom(t)return t[math.random(1,#t)]end
- -- general
- function IsDictionary(t)
- if not(type(t)=='table'and#t==0)then return end
- for i,v in next,t do
- if type(i)=='string'then return true end
- end
- end
- function MergeTables(...)
- local a = {}
- for _,t in next,{...}do
- for _,v in next,t do
- table.insert(a,v)
- end
- end
- return a
- end
- function GetCharactersInRange(a,b)
- local c,d = (a..b):byte(1,2)
- local t = {}
- for i = c, d do table.insert(t, string.char(i))end
- return t
- end
- function GetCharactersInRangeFromString(a)return GetCharactersInRange(unpack(a:split''))end
- function GetCharactersInRangeFromLongerString(a,b)
- local t = {}
- if a then
- for c = 1,#a/2 do
- local pos = c * 2
- local d = a:sub(pos-1,pos)
- table.insert(t,GetCharactersInRangeFromString(d))
- end
- end
- if b then
- table.insert(t,b:split'')
- end
- return FlipTable(MergeTables(unpack(t)))
- end
- function IsAString(str)
- for _,tk in next,{"'",'"',{'[[',']]'}}do
- tk = type(tk)=='string'and{tk,tk}or tk
- local prefix,suffix = unpack(tk)
- local checkprefix,checksuffix =
- str:sub(1,#prefix) == prefix,
- str:sub(#str - #suffix + 1) == suffix
- if checkprefix and checksuffix then
- return str:sub(#prefix + 1,#str - #suffix)
- end
- end
- end
- function LuaStringify(s)
- return '\'' ..
- s:gsub('.',{
- ['\n'] = '\\n';
- ['\\'] = '\\\\';
- ['\t'] = '\\t';
- ["'"] = "\'"
- }) ..
- '\''
- end
- function DeluaStringify(s)
- local char1 = s:sub(1,1)
- local char2 = s:sub(#s)
- local st,en = 2,#s-1
- if char1=='['then
- st+=1
- en-=1
- char1 = '%]'
- end
- s = s:sub(st,en)
- local b = FlipTable{
- ['\n'] = '\\n';
- ['\\'] = '\\\\';
- ['\t'] = '\\t';
- [char2] = "\\"..char2
- }
- return s:gsub('[\\][n\\t'.. char2 .. ']',b)
- end
- -- submain
- function GetBuffersSource(Buffer)
- local t = {}
- for _,a in next,Buffer do
- if a.LeadingWhite~=''then
- table.insert(t,a.LeadingWhite)
- end
- table.insert(t,a.Source)
- end
- return t
- end
- function TableSourceReplace(tblesc,index,option)
- local value = tblesc[index]
- local str = DeluaStringify(value)
- local ExpectedString = type(option.Junkstrings)=='string'and LuaStringify(option.Junkstrings:rep(#str))
- if not ExpectedString then
- local Junkstring = TableRandom(option.Junkstrings)
- local newstr = LuaStringify(Junkstring)
- local lendiff = #str - #Junkstring
- print(str,Junkstring,lendiff)
- local symb = math.sign(lendiff)~=-1 and'+'or'-'
- if symb=='-'then
- lendiff = tostring(lendiff):sub(2)
- end
- ExpectedString = newstr .. symb .. lendiff
- end
- tblesc[index] = ExpectedString
- end
- function TableSourceCompress(tblesc,index)
- local val = DeluaStringify(tblesc[index])
- tblesc[index - 1] = ''
- tblesc[index] = #val
- end
- -- main
- --[[
- Noted Function 1
- Arguments:
- str: Source Code
- dict: Options + arguments
- Refer to the chart below
- ----------------------------------------------------------------------------------------------------
- Index (string) | Value Type | Requirement (Mandatory (M)) | Description
- | | or Value from Index Type |
- ----------------------------------------------------------------------------------------------------
- Type | String | M | Determines result:
- | | | + Replace: Replaces current junkstrings
- | | | with a random junkstring from an
- | | | array or a replacement character
- | | | with the same length
- | | | + Compress: Removes all junkstrings and
- | | | replaces them with their length
- Junkstrings | Array | Replace | Array of junkstrings, chosesn at random
- | | | per iteration
- | String | | Used for replacing junkstrings of those
- | | | of the same length, this string is
- | | | supposed to be one character long, if
- | | | the string is more than one character
- | | | long, then the first character will
- | | | be used
- ----------------------------------------------------------------------------------------------------
- --]]
- function ManageMoonsecSource(Source,Option)
- assert(
- type(Source)=='string'and
- IsDictionary(Option)and
- type(Option.Type)=='string'and
- ({
- Replace = 1;
- Compress = 1
- })[Option.Type]
- ,'Bad argument'
- )
- if Option.Type=='Replace'then
- local Val = Option.Junkstrings
- assert(
- ({
- string = 1;
- table = 1
- })[type(Val)],
- 'Bad argument'
- )
- if type(Val)=='string'and#Val~=0 then
- if#Val==0 then
- Val = ' '
- end
- Option.Junkstrings = Val:sub(1,1)
- end
- end
- local Buffer = CreateLuaTokenStream(Source)
- local TableSource = GetBuffersSource(Buffer)
- for i,v in next,TableSource do
- if TableSource[i-1]=='#'and IsAString(v) then
- JunkstringOptions[Option.Type](TableSource,i,Option)
- end
- end
- return table.concat(TableSource)
- end
- function ManagePSUSource(Source,Option)
- assert(
- type(Source)=='string'and
- IsDictionary(Option)and
- type(Option.Type)=='string'and
- ({
- Replace = 1;
- Compress = 1
- })[Option.Type]
- ,'Bad argument'
- )
- if Option.Type=='Replace'then
- local Val = Option.Junkstrings
- assert(
- ({
- string = 1;
- table = 1
- })[type(Val)],
- 'Bad argument'
- )
- if type(Val)=='string'and#Val~=0 then
- if#Val==0 then
- Val = ' '
- end
- Option.Junkstrings = Val:sub(1,1)
- end
- end
- local Buffer = CreateLuaTokenStream(Source)
- local TableSource = GetBuffersSource(Buffer)
- for i,v in next,TableSource do
- if TableSource[i-2]=='#'and
- TableSource[i-1]=='('and
- IsAString(v)and
- TableSource[i+1]==')'
- then
- for k,v in next,{
- '',
- '#',
- v,
- ''
- }do
- TableSource[i + k - 3] = v
- end
- JunkstringOptions[Option.Type](TableSource,i,Option)
- end
- end
- return table.concat(TableSource)
- end
- -- assignments
- -- renoted
- do
- WhiteChars,CharacterForEscape,AllIdentStartChars,AllIdentChars,Keywords,Digits,HexDigits,
- BinaryDigits,EqualSymbols,CompoundAssignments,Symbols =
- lookifycharactersfromstring' \n\t\r',
- {
- ['"'] = '"',
- ['\\'] = '\\',
- ['a'] = '\a',
- ['b'] = '\b',
- ['f'] = '\f',
- ['n'] = '\n',
- ['r'] = '\r',
- ['t'] = '\t',
- ['v'] = '\v',
- ["'"] = "'"
- },
- GetCharactersInRangeFromLongerString('azAZ','_'),
- GetCharactersInRangeFromLongerString('azAZ09','_'),
- FlipTable{
- 'and',
- 'break',
- 'do',
- 'else',
- 'elseif',
- 'end',
- 'false',
- 'for',
- 'function',
- 'goto',
- 'if',
- 'in',
- 'local',
- 'nil',
- 'not',
- 'or',
- 'repeat',
- 'return',
- 'then',
- 'true',
- 'until',
- 'while'
- },
- GetCharactersInRangeFromLongerString'09',
- GetCharactersInRangeFromLongerString'afAF09',
- FlipTable(('01'):split''),
- GetCharactersInRangeFromLongerString(nil,'~=><'),
- FlipTable{
- '+=',
- '-=',
- '*=',
- '/=',
- '%=',
- '^=',
- '..='
- },
- GetCharactersInRangeFromLongerString(nil,'+-*/^%,{}[]();#.:')
- end
- -- main
- JunkstringFunctions.ManageMoonsecSource = ManageMoonsecSource
- JunkstringFunctions.ManagePSUSource = ManagePSUSource
- JunkstringOptions.Replace = TableSourceReplace
- JunkstringOptions.Compress = TableSourceCompress
- -- return
- return JunkstringFunctions
Add Comment
Please, Sign In to add comment