dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/wire/gates/string.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

411 lines
9.7 KiB
Lua

--[[
String gates ! :P
]]
local MAX_LEN = 1024*1024 -- max string length of 1MB
GateActions("String")
GateActions["string_ceq"] = {
name = "Equal",
inputs = { "A" , "B" },
inputtypes = { "STRING" , "STRING" },
output = function(gate, A, B)
if A == B then return 1 else return 0 end
end,
label = function(Out, A, B)
return string.format ("(%s == %s) = %d", A, B, Out)
end
}
GateActions["string_cineq"] = {
name = "Inequal",
inputs = { "A" , "B" },
inputtypes = { "STRING" , "STRING" },
output = function(gate, A, B)
if A ~= B then return 1 else return 0 end
end,
label = function(Out, A, B)
return string.format ("(%s != %s) = %d", A, B, Out)
end
}
GateActions["string_index"] = {
name = "Index",
inputs = { "A" , "Index" },
inputtypes = { "STRING" , "NORMAL" },
outputtypes = { "STRING" },
output = function(gate, A, B)
if !A then A = "" end
if !B then B = 0 end
return string.sub(A,B,B)
end,
label = function(Out, A, B)
return string.format ("index(%s , %s) = %q", A, B, Out)
end
}
GateActions["string_length"] = {
name = "Length",
inputs = { "A" },
inputtypes = { "STRING" },
output = function(gate, A)
if !A then A = "" end
return #A
end,
label = function(Out, A)
return string.format ("length(%s) = %d", A, Out)
end
}
GateActions["string_upper"] = {
name = "Uppercase",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = "" end
return string.upper(A)
end,
label = function(Out, A)
return string.format ("upper(%s) = %q", A, Out)
end
}
GateActions["string_lower"] = {
name = "Lowercase",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = "" end
return string.lower(A)
end,
label = function(Out, A)
return string.format ("lower(%s) = %q", A, Out)
end
}
GateActions["string_sub"] = {
name = "Substring",
inputs = { "A" , "Start" , "End" },
inputtypes = { "STRING" , "NORMAL" , "NORMAL" },
outputtypes = { "STRING" },
output = function(gate, A, B, C)
if !A then A = "" end
if !B then B = 1 end -- defaults to start of string
if !C then C = -1 end -- defaults to end of string
return string.sub(A,B,C)
end,
label = function(Out, A, B, C)
return string.format ("%s:sub(%s , %s) = %q", A, B, C, Out)
end
}
GateActions["string_explode"] = {
name = "Explode",
inputs = { "A" , "Separator" },
inputtypes = { "STRING" , "STRING" },
outputtypes = { "ARRAY" },
output = function(gate, A, B)
if !A then A = "" end
if !B then B = "" end
return string.Explode(B,A)
end,
label = function(Out, A, B)
return string.format ("explode(%s , %s)", A, B)
end
}
GateActions["string_find"] = {
name = "Find",
inputs = { "A", "B", "StartIndex" },
inputtypes = { "STRING", "STRING" },
outputtypes = { "NORMAL" },
outputs = { "Out" },
output = function(gate, A, B, StartIndex)
local r,_ = string.find(A,B,StartIndex,true)
return r or 0
end,
label = function(Out, A, B)
if istable(Out) then Out = Out.Out end
return string.format ("find(%s , %s) = %d", A, B, Out)
end
}
GateActions["string_concat"] = {
name = "Concatenate",
inputs = { "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" },
inputtypes = { "STRING" , "STRING" , "STRING" , "STRING" , "STRING" , "STRING" , "STRING" , "STRING" },
outputtypes = { "STRING" },
output = function(gate, A, B, C, D, E, F, G, H)
if (A and #A or 0)
+ (B and #B or 0)
+ (C and #C or 0)
+ (D and #D or 0)
+ (E and #E or 0)
+ (F and #F or 0)
+ (G and #G or 0)
+ (H and #H or 0) > MAX_LEN
then
return false
end
local T = {A,B,C,D,E,F,G,H}
return table.concat(T)
end,
label = function(Out)
return string.format ("concat = %q", Out)
end
}
GateActions["string_trim"] = {
name = "Trim",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = "" end
return string.Trim(A)
end,
label = function(Out, A)
return string.format ("trim(%s) = %q", A, Out)
end
}
GateActions["string_replace"] = {
name = "Replace",
inputs = { "String" , "ToBeReplaced" , "Replacer" },
inputtypes = { "STRING" , "STRING" , "STRING" },
outputtypes = { "STRING" },
output = function(gate, A, B, C)
if !A then A = "" end
if !B then B = "" end
if !C then C = "" end
return string.gsub(A,B,C)
end,
label = function(Out, A, B, C)
return string.format ("%s:replace(%s , %s) = %q", A, B, C, Out)
end
}
GateActions["string_reverse"] = {
name = "Reverse",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = "" end
return string.reverse(A)
end,
label = function(Out, A)
return string.format ("reverse(%s) = %q", A, Out)
end
}
GateActions["string_tonum"] = {
name = "To Number",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "NORMAL" },
output = function(gate, A)
if !A then A = "" end
return tonumber(A)
end,
label = function(Out, A)
return string.format ("tonumber(%s) = %d", A, Out)
end
}
GateActions["string_tostr"] = {
name = "Number to String",
inputs = { "A" },
inputtypes = { "NORMAL" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = 0 end
return tostring(A)
end,
label = function(Out, A)
return string.format ("tostring(%s) = %q", A, Out)
end
}
GateActions["string_tobyte"] = {
name = "To Byte",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "NORMAL" },
output = function(gate, A)
if !A then A = "" end
return string.byte(A)
end,
label = function(Out, A)
return string.format ("tobyte(%s) = %d", A, Out)
end
}
GateActions["string_tochar"] = {
name = "To Character",
inputs = { "A" },
inputtypes = { "NORMAL" },
outputtypes = { "STRING" },
output = function(gate, A)
if !A then A = 0 end
return string.char(A)
end,
label = function(Out, A)
return string.format ("tochar(%s) = %q", A, Out)
end
}
GateActions["string_repeat"] = {
name = "Repeat",
inputs = { "A" , "Num"},
inputtypes = { "STRING" , "NORMAL" },
outputtypes = { "STRING" },
output = function(gate, A, B)
if !A then A = "" end
if !B or B<1 then B = 1 end
if B * #A > MAX_LEN then return false end
return string.rep(A,B)
end,
label = function(Out, A)
return string.format ("repeat(%s) = %q", A, Out)
end
}
GateActions["string_ident"] = {
name = "Identity",
inputs = { "A" },
inputtypes = { "STRING" },
outputtypes = { "STRING" },
output = function(gate, A )
return A
end,
label = function(Out, A)
return string.format ("%s = %s", A, Out)
end
}
GateActions["string_select"] = {
name = "Select",
inputs = { "Choice", "A", "B", "C", "D", "E", "F", "G", "H" },
inputtypes = { "NORMAL", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING" },
outputtypes = { "STRING" },
output = function(gate, Choice, ...)
return ({...})[math.Clamp(Choice,1,8)]
end,
label = function(Out, Choice)
return string.format ("select(%s) = %s", Choice, Out)
end
}
GateActions["string_to_memory"] = {
name = "String => Memory",
inputs = { "A" },
inputtypes = { "STRING" },
outputs = { "Memory" },
reset = function(gate)
gate.stringQueued = false
gate.stringChanged = false
gate.currentString = ""
end,
output = function(gate, A)
if (A ~= gate.currentString) then
if (not gate.stringChanged) then
gate.stringChanged = true
gate.currentString = A
gate.stringQueued = false
else
gate.stringQueued = true
end
end
return gate.Outputs["Memory"].Value --This will prevent Wire_TriggerOutput from changing anything
end,
ReadCell = function(self, gate, Address)
if (Address == 0) then --Clk
if (gate.stringChanged) then return 1 else return 0 end
elseif (Address == 1) then --String length
return #(gate.currentString)
else --Return string bytes
local index = Address - 1
if (index > #(gate.currentString)) then -- Check whether requested address is outside the string
return 0
else
return string.byte(gate.currentString, index)
end
end
end,
WriteCell = function(self, gate, Address, value)
if (Address == 0) and (value == 0) then --String got accepted
gate.stringChanged = false
if gate.stringQueued then --Get queued string
gate.stringQueued = false
gate.currentString = gate.Inputs["A"].Value
gate.stringChanged = true
end
return true
else
return false
end
end
}
GateActions["string_from_memory"] = {
name = "Memory => String",
inputs = {},
outputs = { "Out", "Memory" },
outputtypes = { "STRING", "NORMAL" },
reset = function(gate) --initialize the gate
gate.memory = {}
gate.stringLength = 0
gate.currentString = ""
gate.ready = true
end,
output = function(gate)
return gate.currentString, gate.Outputs["Memory"].Value
end,
ReadCell = function(self, gate, address)
if (address == 0) then
return 0
elseif (address == 1) then
return gate.stringLength
else
return gate.memory[address-1] or 0 -- "or 0" to prevent it from returning nil if index is outside the array
end
end,
WriteCell = function(self, gate, address, value)
if (value >= 0) then
if (address == 0) and (value == 1) then -- Clk has been set
local maxIndex = gate.stringLength
for i=1,gate.stringLength,1 do
if not gate.memory[i] then
maxIndex = i-1
break
end
end
gate.currentString = string.char(unpack(gate.memory, 1, maxIndex))
gate:CalcOutput()
return true
elseif (address == 1) then -- Set string length
gate.stringLength = math.floor(value)
return true
elseif (address > 1) then -- Set memory cell
gate.memory[address-1] = math.floor(value)
return true
end
end
return false; -- if (value < 0) or ((address == 0) and (value != 1))
end
}
GateActions()