From 5ffd85bf9194b0570ee06d6757b5d39f226c70ab Mon Sep 17 00:00:00 2001 From: Tad Hardesty Date: Fri, 24 Aug 2018 02:39:05 -0700 Subject: [PATCH] Parse non-strings in lists in maps (#39786) * Parse non-strings in lists in maps * Fix 'listening' var --- code/__HELPERS/_lists.dm | 14 ++++++- code/modules/mapping/reader.dm | 74 +++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 8ada0c20b83..fed283adcdd 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -489,8 +489,18 @@ return l . = l.Copy() for(var/i = 1 to l.len) - if(islist(.[i])) - .[i] = .(.[i]) + var/key = .[i] + if(isnum(key)) + // numbers cannot ever be associative keys + continue + var/value = .[key] + if(islist(value)) + value = deepCopyList(value) + .[key] = value + if(islist(key)) + key = deepCopyList(key) + .[i] = key + .[key] = value //takes an input_key, as text, and the list of keys already used, outputting a replacement key in the format of "[input_key] ([number_of_duplicates])" if it finds a duplicate //use this for lists of things that might have the same name, like mobs or objects, that you plan on giving to a player as input diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index 2889a6c932a..c243e00035b 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -409,57 +409,67 @@ //build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7)) //return the filled list /datum/parsed_map/proc/readlist(text as text, delimiter=",") - - var/list/to_return = list() + . = list() + if (!text) + return var/position var/old_position = 1 - do - //find next delimiter that is not within "..." + while(position != 0) + // find next delimiter that is not within "..." position = find_next_delimiter_position(text,old_position,delimiter) - //check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7)) + // check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7)) var/equal_position = findtext(text,"=",old_position, position) - var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position)),1)//the name of the variable, must trim quotes to build a BYOND compliant associatives list + var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position))) + var/left_constant = delimiter == ";" ? trim_left : parse_constant(trim_left) old_position = position + 1 - if(equal_position)//associative var, so do the association - var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable + if(equal_position && !isnum(left_constant)) + // Associative var, so do the association. + // Note that numbers cannot be keys - the RHS is dropped if so. + var/trim_right = trim_text(copytext(text,equal_position+1,position)) + var/right_constant = parse_constant(trim_right) + .[left_constant] = right_constant - //Check for string - if(findtext(trim_right,"\"",1,2)) - trim_right = copytext(trim_right,2,findtext(trim_right,"\"",3,0)) + else // simple var + . += list(left_constant) - //Check for number - else if(isnum(text2num(trim_right))) - trim_right = text2num(trim_right) +/datum/parsed_map/proc/parse_constant(text) + // number + var/num = text2num(text) + if(isnum(num)) + return num - //Check for null - else if(trim_right == "null") - trim_right = null + // string + if(findtext(text,"\"",1,2)) + return copytext(text,2,findtext(text,"\"",3,0)) - //Check for list - else if(copytext(trim_right,1,5) == "list") - trim_right = readlist(copytext(trim_right,6,length(trim_right))) + // list + if(copytext(text,1,6) == "list(") + return readlist(copytext(text,6,length(text))) - //Check for file - else if(copytext(trim_right,1,2) == "'") - trim_right = file(copytext(trim_right,2,length(trim_right))) + // typepath + var/path = text2path(text) + if(ispath(path)) + return path - //Check for path - else if(ispath(text2path(trim_right))) - trim_right = text2path(trim_right) + // file + if(copytext(text,1,2) == "'") + return file(copytext(text,2,length(text))) - to_return[trim_left] = trim_right + // null + if(text == "null") + return null - else//simple var - to_return[trim_left] = null + // not parsed: + // - pops: /obj{name="foo"} + // - new(), newlist(), icon(), matrix(), sound() - while(position != 0) - - return to_return + // fallback: string + return text /datum/parsed_map/Destroy() ..()