C语言各种数据类型校验工具(Java实现)

C语言各种数据类型校验工具(Java实现)

package com.example.demo.utils;

@Slf4j
public class CheckValidDataSpecsUtil {

    public static boolean isValidSpecs(final int dataType, final String specs) {
        switch (dataType) {
            case 8:// struct型 不可为空
                return isValidStructSpecs(specs, 4);

            case 7:// array型 不可为空
                return isValidArraySpecs(JSON.parseObject(specs));

            default:
                return isValidCommonSpecs(dataType, specs);
        }
    }

    private static boolean isValidStructSpecs(String specs, int level) {
        JSONArray retArray = JSON.parseArray(specs);
        if (CollectionUtils.isEmpty(retArray)) {
            throw new BusinessException("结构体数据规格定义不允许为空!");
        }
        Set<String> identifierSet = new HashSet<>();
        for (int i = 0; i < retArray.size(); i++) {

            JSONObject jsonObject = retArray.getJSONObject(i);
            log.info("jsonObject = {}, i = {}", jsonObject, i);
            if (jsonObject == null
                    || !jsonObject.containsKey(IDENTIFIER)
                    || !jsonObject.containsKey(NAME)
                    || !jsonObject.containsKey(DATA_TYPE)
                    || !jsonObject.containsKey(DESCRIPTION)) {
                return false;
            }

            if (!isValidNaming4Name(jsonObject.getString(NAME))) {
                log.error("名称,长度异常或者是名称不合法");
                return false;
            }
            if (!isValidNaming4Identifier(jsonObject.getString(IDENTIFIER))) {
                log.error("标识符,长度异常或者是名称不合法");
                return false;

            }
            identifierSet.add(jsonObject.getString(IDENTIFIER));
            JSONObject dataTypeObject = jsonObject.getJSONObject(DATA_TYPE);
            if (!dataTypeObject.containsKey(TYPE) || !dataTypeObject.containsKey(SPECS)) {
                log.error("结构体校验,子元素缺少key dataTypeObject = {}", dataTypeObject);
                return false;
            }

            if (dataTypeObject.getIntValue(TYPE) == 8) {
                level = level - 1;
                if (!isValidStructSpecs(dataTypeObject.getString(SPECS), level)) {
                    log.error("结构体校验嵌套结构体,specs = {}", dataTypeObject.getString(SPECS));
                    return false;
                }

            }
            if (dataTypeObject.getIntValue(TYPE) == 7) {
                if (!isValidArraySpecsByArraySpecsAndLevel(dataTypeObject.getString(SPECS), level - 1))
                    return false;
            }
            // 如果struct当前层级没有数组、结构体数据规格定义,将level设为0
            if (dataTypeObject.getIntValue(TYPE) != 8 && dataTypeObject.getIntValue(TYPE) != 7) {
                int type = dataTypeObject.getIntValue(TYPE);
                String specsInner = dataTypeObject.getString(SPECS);
                // level = 0;
                if (!isValidCommonSpecs(type, specsInner)) {
                    log.error("结构体内层定义: type = {}, specsInner = {}", type, specsInner);
                    return false;
                }
            }
            // level = 0;
        }
        if (identifierSet.size() != retArray.size()) {
            return false;
        }
        return true;
    }

    private static boolean isValidArraySpecsByArraySpecsAndLevel(String arraySpecs, int level) {
        try {
            JSONObject arrayJSONObject = JSONObject.parseObject(arraySpecs);

            if (arrayJSONObject.containsKey(SIZE)
                    && ((Integer) arrayJSONObject.get(SIZE) >= 0
                    && (Integer) arrayJSONObject.get(SIZE) <= 65535)
                    && arrayJSONObject.containsKey(ITEM)
                    && arrayJSONObject.get(ITEM) != null) {
                JSONObject itemJSONObject = arrayJSONObject.getJSONObject(ITEM);
                if (!itemJSONObject.containsKey(DATA_TYPE)) {
                    log.error("===> isValidArraySpecs array型,数据规格定义 itemJSONObject = {} 错误!缺少dataType节点", itemJSONObject);
                    return false;
                }
                JSONObject dataTypeJSONObject = itemJSONObject.getJSONObject(DATA_TYPE);
                if (!dataTypeJSONObject.containsKey(TYPE) || !dataTypeJSONObject.containsKey(SPECS)) {
                    log.error("===> array型,数据规格定义 dataTypeJSONObject = {} 错误!必须有节点specs和type", dataTypeJSONObject);
                    return false;
                }
                int type = dataTypeJSONObject.getInteger(TYPE);
                String specs = dataTypeJSONObject.getString(SPECS);
                // 数组下不能包含Bytes、数组
                if (0 == type || 7 == type) {
                    log.error("===> array型,数据规格定义 数组层级下不能是Bytes或者数组 {}", dataTypeJSONObject);
                    return false;
                }
                // 结构体校验
                if (8 == type && dataTypeJSONObject.containsKey(SPECS)) {
                    boolean validStructSpecs = isValidStructSpecs(dataTypeJSONObject.getString(SPECS), level - 1);
                    if (!validStructSpecs) {
                        log.error("===> array型,数据规格定义 数组层级下结构体不合法 {}", dataTypeJSONObject);
                        return false;
                    }
                }

                // 数组里的普通类型
                if (type == 1 || type == 2 || type == 3 || type == 4 || type == 5 || type == 6) {
                    if (!isValidCommonSpecs(type, specs)) {
                        log.error("结构体内层定义,一般数据类型: type = {}, specs = {}", type, specs);
                        return false;
                    }
                }
                return true;
            } else {
                log.error("===> array型,数据规格定义 {} 错误!节点缺少或者个数不在规定范围内", arrayJSONObject);
                return false;
            }
        } catch (Exception e) {
            if (e instanceof BusinessException)
                throw e;
            log.error("===> array型,数据规格定义错误!某些节点解析错误!");
            return false;
        }
    }

    private static boolean isValidArraySpecs(JSONObject arrayJSONObject) {
        try {
            if (arrayJSONObject != null && arrayJSONObject.containsKey(SIZE)
                    && ((arrayJSONObject.getIntValue(SIZE) > 0
                    && arrayJSONObject.getIntValue(SIZE) <= 65535))
                    && arrayJSONObject.containsKey(ITEM)
                    && arrayJSONObject.get(ITEM) != null) {
                JSONObject itemJSONObject = arrayJSONObject.getJSONObject(ITEM);
                if (!itemJSONObject.containsKey(DATA_TYPE)) {
                    log.error("===> isValidArraySpecs array型,数据规格定义 itemJSONObject = {} 错误!缺少dataType节点", itemJSONObject);
                    return false;
                }
                JSONObject dataTypeJSONObject = itemJSONObject.getJSONObject(DATA_TYPE);
                if (!dataTypeJSONObject.containsKey(TYPE) || !dataTypeJSONObject.containsKey(SPECS)) {
                    log.error("===> array型,数据规格定义 dataTypeJSONObject = {} 错误!必须有节点specs和type", dataTypeJSONObject);
                    return false;
                }
                int type = dataTypeJSONObject.getIntValue(TYPE);
                String specs = dataTypeJSONObject.getString(SPECS);
                if (0 == type || 7 == type) {
                    log.error("===> array型,数据规格定义 数组层级下不能是Bytes或者数组 {}", dataTypeJSONObject);
                    return false;
                }
                // 结构体校验
                if (8 == type && dataTypeJSONObject.containsKey(SPECS)) {
                    boolean validStructSpecs = isValidStructSpecs(specs, 2);
                    if (!validStructSpecs) {
                        log.error("===> array型,数据规格定义 数组层级下结构体不合法 {}", dataTypeJSONObject);
                        return false;
                    }
                }
                // 数组里的普通类型
                if (type == 1 || type == 2 || type == 3 || type == 4 || type == 5 || type == 6) {
                    if (!isValidCommonSpecs(type, specs)) return false;
                }
                return true;
            } else {
                log.error("===> array型,数据规格定义为空!");
                return true;
            }
        } catch (Exception e) {
            if (e instanceof BusinessException)
                throw e;
            return false;
        }
    }

    private static boolean isValidCommonSpecs(int dataType, String specs) {
        JSONObject specsRet = new JSONObject();
        JSONObject parseObject;
        try {
            parseObject = JSON.parseObject(specs);
            if (dataType != 4 && parseObject == null) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        switch (dataType) {
            case 0: // Bytes型
/**
 * {"min":"","max":"","step":"","unit":"","length":1024}
 */
                if (parseObject != null && parseObject.containsKey(LENGTH) && parseObject.get(LENGTH) != null) {
                    int length;
                    try {
                        length = parseObject.getIntValue(LENGTH);
                    } catch (Exception e) {
                        return false;
                    }
                    if (length <= 0 || 65535 < length) {
                        return false;
                    }
                } else {
                    log.error("===> Bytes型,数据规格定义 {} 错误!", specs);
                    return false;
                }
                break;
            case 1: // float型 TODO 精细化浮点型数据 string
                /**
                 * {"min":"0.1","max":"11.0","step":"0.1","unit":"min","range":["0.1","11.0"]}
                 * 需要注意的是单位能不能为空
                 */

                if (parseObject.containsKey(STEP)
                        && parseObject.containsKey(UNIT)
                        && parseObject.containsKey(MAX)
                        && parseObject.containsKey(MIN)) {
                    if (parseObject.get(STEP) == null
                            || parseObject.get(UNIT) == null
                            || parseObject.get(MIN) == null
                            || parseObject.get(MAX) == null) { // key 对应的 value不能为空
                        log.error("float型,数据规格定义错误!value不能为空");
                        return false;
                    }

                    String minStr = parseObject.getString(MIN);
                    String maxStr = parseObject.getString(MAX);
                    String stepStr = parseObject.getString(STEP);
                    if (!isValidDouble(maxStr) || !isValidDouble(minStr) || !isValidDouble(stepStr)) {
                        log.error("浮点型数据定义错误!");
                        return false;
                    }

                    BigDecimal min, max, step;
                    try {
                        min = new BigDecimal(parseObject.getString(MIN));
                        max = new BigDecimal(parseObject.getString(MAX));
                        step = new BigDecimal(parseObject.getString(STEP));
                    } catch (Exception e) {
                        return false;
                    }

                    BigDecimal maxValue = new BigDecimal("9007199254740991.0");
                    BigDecimal minValue = new BigDecimal("-9007199254740992.0");
                    if (max.compareTo(maxValue) > 0) {
                        log.error("浮点型数据超过最大值!");
                        return false;
                    }

                    specsRet.put(RANGE, Arrays.asList(parseObject.getDoubleValue(MIN), parseObject.getDoubleValue(MAX)));
                    if (min.compareTo(minValue) < 0) {
                        log.error("浮点型数据不能小于最小值!");
                        return false;
                    }

                    try {
                        parseObject.getDoubleValue(STEP);
                    } catch (Exception e) {
                        log.error("浮点型,数据规格定义错误! step不能转为浮点型数据!");
                        return false;
                    }

                    if (step.compareTo(BigDecimal.ZERO) < 0) {
                        log.error("浮点型,数据规格定义错误 步长必须非负!");
                        return false;
                    }
                    if (min.add(step).compareTo(max) > 0) {
                        throw new BusinessException("浮点型,数据规格定义错误 步长错误!最小值加上一个步长不能大于最大值");

                    }
                } else {
                    log.error("===> 浮点型,数据规格定义 {} 错误!", specs);
                    return false;
                }
                break;
            case 2: // int型
/**
 * {"min":1,"max":10,"step":1,"unit":"min"}
 * 需要注意的是单位能不能为空
 */

                if (parseObject.containsKey(STEP)
                        && parseObject.containsKey(UNIT)
                        && parseObject.containsKey(MIN)
                        && parseObject.containsKey(MAX)) {
                    if (parseObject.get(STEP) == null
                            || parseObject.get(UNIT) == null
                            || parseObject.get(MIN) == null
                            || parseObject.get(MAX) == null) {
                        // key 对应的 value不能为空
                        throw new BusinessException("int型,数据规格定义错误!value不能为空");
                    }
                }
                String numMax = parseObject.getString(MAX);
                String numMin = parseObject.getString(MIN);
                String numStep = parseObject.getString(STEP);
                if (!isValidNumStr(numMax) || !isValidNumStr(numMin) || !isValidNumStr(numStep)) {
                    log.error("不能转换成数值!{}", specs);
                    return false;
                }
                if (numMax.replaceAll("-", "").length() > 16 || numMin.replaceAll("-", "").length() > 16 || numStep.replaceAll("-", "").length() > 16) {
                    log.error("超过最大整型表示范围!{}", specs);
                    return false;
                }
                long step;
                long min;
                long max = parseObject.getLongValue(MAX);

                step = parseObject.getLongValue(STEP);
                min = parseObject.getLongValue(MIN);
                String maxStr = parseObject.getString(MAX);
                if (new BigDecimal(maxStr).compareTo(new BigDecimal(LONG_MAX_VALUE)) > 0) {
                    throw new BusinessException("最大值错误!");
                }

                if (new BigDecimal(LONG_MIN_VALUE).compareTo(new BigDecimal(min)) > 0)
                    throw new BusinessException("最小值错误!");

                if (step < 0) {
                    throw new BusinessException("int型,数据规格定义错误 步长必须为正整数!");
                }

                if (IoTALUtil.addWithNoScale(new BigDecimal(step), new BigDecimal(min)).compareTo(new BigDecimal(max)) > 0) {
                    throw new BusinessException("int型,数据规格定义错误 步长错误!最小值加上一个步长不能大于最大值");
                }

        } else{
            throw new BusinessException("===> int型,数据规格定义错误!specs = " + specs);

        }
        break;
        case 3: // text型
/**
 * {"length":1024}
 * 设计文档
 * rule String 文本合法校验规则,正则表达式,允许填空
 * * length Int32 字符串最大长度,整型值,必须大于0,允许最大长度65535
 * */

        if (parseObject.containsKey(LENGTH) && parseObject.get(LENGTH) != null) {
            int textLength;
            try {
                textLength = parseObject.getIntValue(LENGTH);
            } catch (Exception e) {
                throw new BusinessException("===> text型,数据规格定义 length错误!length = " + parseObject.get(LENGTH));
            }
            if (0 < textLength && 65535 >= textLength) {
                return true;
                // specsRet.put(LENGTH, parseObject.get(LENGTH));
                // if (parseObject.containsKey(RULE)) {
                // specsRet.put(RULE, parseObject.get(RULE));
                // }
            } else {
                return false;
            }
        } else {
            log.error("===> text型,数据规格定义 {} 错误!", specs);
            return false;
        }
        case 4: // date型
        if (parseObject.size() != 0)
            return false;
        break;
        case 5: // bool型
        if (!parseObject.containsKey("0")
                || parseObject.get("0") == null
                || !parseObject.containsKey("1")
                || parseObject.get("1") == null) {
            log.error("===> bool型,数据规格定义 {} 错误!", specs);
            return false;
        }
        break;
        case 6: // enum型
        if (parseObject.containsKey("list") && parseObject.get("list") != null ) {
        // enum 外层结构正确 校验数组内部元素
            List<SpecsEnumDTO> specsEnumDTOS;
            String list = parseObject.getString("list");
            JSONArray objects = JSON.parseArray(list);
            int size = objects.size();
            for (int i = 0; i < size; i++) {
                JSONObject o = (JSONObject) JSON.parseArray(list).get(i);
                if (!o.containsKey("description") || !o.containsKey("value") || o.size() != 2) {
                    log.error("枚举类型校验失败,缺少description字段!i = {}, JSONObject = {}", i, o);
                    return false;
                }
            }

            try {
                specsEnumDTOS = JSON.parseArray(list, SpecsEnumDTO.class);
            } catch (Exception e) {
                log.error("=====>ProductPropertiesService#add#switch case 6 enum: " + parseObject.get("list"));
                return false;
            }
            if (CollectionUtils.isEmpty(specsEnumDTOS)) {
                log.error("=====>ProductPropertiesService#add#switch case 6 enum definition specs is empty list! ");
                return false;
            }
            Set<Long> collect = specsEnumDTOS.stream().map(SpecsEnumDTO::getValue).collect(Collectors.toSet());
            boolean present = collect.stream().anyMatch(a -> a > INT_MAX_VALUE || a < INT_MIN_VALUE);
            if (present) {
                log.error("enum型,数据规格定义错误!枚举定义值超过范围");
                return false;
            }
            if (collect.size() < specsEnumDTOS.size()) {
                log.error("enum型,数据规格定义错误!枚举定义重复");
                return false;
            }
        } else {
            log.error("===> enum型,数据规格定义 {} 错误!", specs);
            return false;
        }
        break;
        case 7: // array型 数组可以有0个元素 0~65535 数组下不能有:数组、Bytes
        boolean isValidArray = isValidArraySpecs(parseObject);
        if (!isValidArray) {
            return false;
        }
        break;
    }
return true;
}


    public static boolean isValidNumStr(String num) {
        if ("0".equals(num)) return true;
        if (StringUtils.isNotEmpty(num)) {
            return num.matches("^[\\-1-9]+[0-9]*$");
        }
        return false;
    }

    public static boolean isValidNaming4Identifier(final String identifier) {
        List<String> commonTypes = Arrays.asList("byte", "int", "float", "double", "char", "array", "enum", "struct", "bool");
        if (commonTypes.contains(identifier)) {
            log.error("基本类型不能作为标识符!");
            return false;
        }
        if (identifier.length() < 1 || identifier.length() > 64) {
            log.error("标识符长度异常!");
            return false;
        }
        String regx = "^[_a-zA-Z0-9]+$";
        Pattern p = Pattern.compile(regx);
        Matcher matcher = p.matcher(identifier);
        return matcher.find();
    }
    
    public static boolean isValidNaming4Name(String identifier) {
        if (identifier.length() < 1 || identifier.length() > 64) {
            log.error("标识符长度异常!");
            return false;
        }
        String regx = "^[_A-Za-z0-9\\-\\u4e00-\\u9fa5]+$";
        Pattern p = Pattern.compile(regx);
        Matcher matcher = p.matcher(identifier);
        return matcher.find();
    }

    public static boolean isValidDouble(String doubleStr) {
        if (StringUtils.isNotEmpty(doubleStr)) {
            String regx = "^(-?\\d+)(\\.\\d{0,6})?$";
            Pattern p = Pattern.compile(regx);
            Matcher matcher = p.matcher(doubleStr);
            return matcher.find();
        }
        return false;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值