# https://github.com/sbellus/json-cmake/blob/master/JSONParser.cmake cmake_minimum_required(VERSION 3.1) if (DEFINED JSonParserGuard) return() endif() set(JSonParserGuard yes) macro(sbeParseJson prefix jsonString) cmake_policy(PUSH) set(json_string "${${jsonString}}") string(LENGTH "${json_string}" json_jsonLen) set(json_index 0) set(json_AllVariables ${prefix}) set(json_ArrayNestingLevel 0) set(json_MaxArrayNestingLevel 0) _sbeParse(${prefix}) unset(json_index) unset(json_AllVariables) unset(json_jsonLen) unset(json_string) unset(json_value) unset(json_inValue) unset(json_name) unset(json_inName) unset(json_newPrefix) unset(json_reservedWord) unset(json_arrayIndex) unset(json_char) unset(json_end) unset(json_ArrayNestingLevel) foreach(json_nestingLevel RANGE ${json_MaxArrayNestingLevel}) unset(json_${json_nestingLevel}_arrayIndex) endforeach() unset(json_nestingLevel) unset(json_MaxArrayNestingLevel) cmake_policy(POP) endmacro() macro(sbeClearJson prefix) foreach(json_var ${${prefix}}) unset(${json_var}) endforeach() unset(${prefix}) unset(json_var) endmacro() macro(sbePrintJson prefix) foreach(json_var ${${prefix}}) message("${json_var} = ${${json_var}}") endforeach() endmacro() macro(_sbeParse prefix) while(${json_index} LESS ${json_jsonLen}) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if("\"" STREQUAL "${json_char}") _sbeParseNameValue(${prefix}) elseif("{" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() _sbeParseObject(${prefix}) elseif("[" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() _sbeParseArray(${prefix}) endif() if(${json_index} LESS ${json_jsonLen}) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) else() break() endif() if ("}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") break() endif() _sbeMoveToNextNonEmptyCharacter() endwhile() endmacro() macro(_sbeParseNameValue prefix) set(json_name "") set(json_inName no) while(${json_index} LESS ${json_jsonLen}) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) # check if name ends if("\"" STREQUAL "${json_char}" AND json_inName) set(json_inName no) _sbeMoveToNextNonEmptyCharacter() if(NOT ${json_index} LESS ${json_jsonLen}) break() endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) set(json_newPrefix ${prefix}.${json_name}) set(json_name "") if(":" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() if(NOT ${json_index} LESS ${json_jsonLen}) break() endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if("\"" STREQUAL "${json_char}") _sbeParseValue(${json_newPrefix}) break() elseif("{" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() _sbeParseObject(${json_newPrefix}) break() elseif("[" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() _sbeParseArray(${json_newPrefix}) break() else() # reserved word starts _sbeParseReservedWord(${json_newPrefix}) break() endif() else() # name without value list(APPEND ${json_AllVariables} ${json_newPrefix}) set(${json_newPrefix} "") break() endif() endif() if(json_inName) # remove escapes if("\\" STREQUAL "${json_char}") math(EXPR json_index "${json_index} + 1") if(NOT ${json_index} LESS ${json_jsonLen}) break() endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) endif() set(json_name "${json_name}${json_char}") endif() # check if name starts if("\"" STREQUAL "${json_char}" AND NOT json_inName) set(json_inName yes) endif() _sbeMoveToNextNonEmptyCharacter() endwhile() endmacro() macro(_sbeParseReservedWord prefix) set(json_reservedWord "") set(json_end no) while(${json_index} LESS ${json_jsonLen} AND NOT json_end) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if("," STREQUAL "${json_char}" OR "}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") set(json_end yes) else() set(json_reservedWord "${json_reservedWord}${json_char}") math(EXPR json_index "${json_index} + 1") endif() endwhile() list(APPEND ${json_AllVariables} ${prefix}) string(STRIP "${json_reservedWord}" json_reservedWord) set(${prefix} ${json_reservedWord}) endmacro() macro(_sbeParseValue prefix) cmake_policy(SET CMP0054 NEW) # turn off implicit expansions in if statement set(json_value "") set(json_inValue no) while(${json_index} LESS ${json_jsonLen}) # fast path for copying strings if (json_inValue) # attempt to gobble up to 128 bytes of string string(SUBSTRING "${json_string}" ${json_index} 128 try_gobble) # consume a piece of string we can just straight copy before encountering \ or " string(REGEX MATCH "^[^\"\\\\]+" simple_copy "${try_gobble}") string(CONCAT json_value "${json_value}" "${simple_copy}") string(LENGTH "${simple_copy}" copy_length) math(EXPR json_index "${json_index} + ${copy_length}") endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) # check if json_value ends, it is ended by " if("\"" STREQUAL "${json_char}" AND json_inValue) set(json_inValue no) set(${prefix} ${json_value}) list(APPEND ${json_AllVariables} ${prefix}) _sbeMoveToNextNonEmptyCharacter() break() endif() if(json_inValue) # if " is escaped consume if("\\" STREQUAL "${json_char}") math(EXPR json_index "${json_index} + 1") if(NOT ${json_index} LESS ${json_jsonLen}) break() endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if(NOT "\"" STREQUAL "${json_char}") # if it is not " then copy also escape character set(json_char "\\${json_char}") endif() endif() _sbeAddEscapedCharacter("${json_char}") endif() # check if value starts if("\"" STREQUAL "${json_char}" AND NOT json_inValue) set(json_inValue yes) endif() math(EXPR json_index "${json_index} + 1") endwhile() endmacro() macro(_sbeAddEscapedCharacter char) string(CONCAT json_value "${json_value}" "${char}") endmacro() macro(_sbeParseObject prefix) _sbeParse(${prefix}) _sbeMoveToNextNonEmptyCharacter() endmacro() macro(_sbeParseArray prefix) math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} + 1") set(json_${json_ArrayNestingLevel}_arrayIndex 0) set(${prefix} "") list(APPEND ${json_AllVariables} ${prefix}) while(${json_index} LESS ${json_jsonLen}) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if("\"" STREQUAL "${json_char}") # simple value list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) _sbeParseValue(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) elseif("{" STREQUAL "${json_char}") # object _sbeMoveToNextNonEmptyCharacter() list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) _sbeParseObject(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) else() list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) _sbeParseReservedWord(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) endif() if(NOT ${json_index} LESS ${json_jsonLen}) break() endif() string(SUBSTRING "${json_string}" ${json_index} 1 json_char) if("]" STREQUAL "${json_char}") _sbeMoveToNextNonEmptyCharacter() break() elseif("," STREQUAL "${json_char}") math(EXPR json_${json_ArrayNestingLevel}_arrayIndex "${json_${json_ArrayNestingLevel}_arrayIndex} + 1") endif() _sbeMoveToNextNonEmptyCharacter() endwhile() if(${json_MaxArrayNestingLevel} LESS ${json_ArrayNestingLevel}) set(json_MaxArrayNestingLevel ${json_ArrayNestingLevel}) endif() math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} - 1") endmacro() macro(_sbeMoveToNextNonEmptyCharacter) math(EXPR json_index "${json_index} + 1") if(${json_index} LESS ${json_jsonLen}) string(SUBSTRING "${json_string}" ${json_index} 1 json_char) while(${json_char} MATCHES "[ \t\n\r]" AND ${json_index} LESS ${json_jsonLen}) math(EXPR json_index "${json_index} + 1") string(SUBSTRING "${json_string}" ${json_index} 1 json_char) endwhile() endif() endmacro()