ci核心导入input类BUG将json数组中的数字转成了字符串

本文探讨了在PHP中加载INPUT类前后$_POST数据类型的差异,特别是在系统钩子中使用json_decode对原始$_POST数据进行处理后的影响。

先来看下代码:

echo 'load INPUT类之前:';
        var_dump($_POST);
	$IN	=& load_class('Input', 'core');        
echo 'load INPUT类之后:';
var_dump($_POST);exit;

结果:



看到了吗,$_POST的数据格式不同,INT变成了STRING

但也许和我的操作有关,因为我是在系统钩子里对$_POST原始数据进行了json_decode修改

$_POST['data']   =@json_decode($_POST['data'],true);


所以我把这句话放到了上层勾子中,也就是load input之后的。暂时没发现其他问题。






import json import re import logging import sys from pathlib import Path from shutil import copy2 from datetime import datetime from argparse import ArgumentParser # ------------------------------- # 🔧 新增:日志文件配置 # ------------------------------- # 正确获取项目根目录 PROJECT_ROOT = Path(__file__).parent.parent.resolve() LOG_DIR = PROJECT_ROOT / "output" / "log" # ✅ 关键:必须加上 parents=True 才能自动创建 output/ LOG_DIR.mkdir(parents=True, exist_ok=True) # 生成带时间戳的日志文件名 LOG_FILE = LOG_DIR / f"range_sync_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" class CLMRangeSynchronizer: def __init__(self, manifest_path="output/generated_ranges_manifest.json", c_file_path="input/wlc_clm_data_6726b0.c", dry_run=False): self.manifest_path = Path(manifest_path) self.c_file_path = Path(c_file_path) self.dry_run = dry_run # 是否为预览模式 if not self.manifest_path.exists(): raise FileNotFoundError(f"找不到 manifest 文件: {self.manifest_path}") if not self.c_file_path.exists(): raise FileNotFoundError(f"找不到 C 源文件: {self.c_file_path}") self.used_ranges = [] self.array_macros = {} self.struct_entries = {} self.start_marker = "// === START CHANNEL RANGES" self.end_marker = "// === END CHANNEL RANGES" # ✅ 在实例化时获取 logger(避免全局变量) self.logger = logging.getLogger(__name__) def load_manifest(self): """加载并解析 generated_ranges_manifest.json""" with open(self.manifest_path, 'r', encoding='utf-8') as f: data = json.load(f) if "used_ranges" not in data: raise KeyError("❌ manifest 文件缺少 'used_ranges' 字段") valid_ranges = [] for item in data["used_ranges"]: if isinstance(item, str) and re.match(r'^RANGE_[\w\d_]+_\d+_\d+$', item): valid_ranges.append(item) else: self.logger.warning(f"跳过无效项: {item}") self.used_ranges = sorted(set(valid_ranges)) self.logger.info(f"已加载 {len(self.used_ranges)} 个有效 RANGE 宏") def parse_c_arrays(self): """解析 C 文件中的 channel_ranges_xxx[] 数组""" content = self.c_file_path.read_text(encoding='utf-8') start_idx = content.find(self.start_marker) end_idx = content.find(self.end_marker) if start_idx == -1 or end_idx == -1: raise ValueError("未找到 CHANNEL RANGES 注释锚点") block = content[start_idx:end_idx] pattern = re.compile( r'static\s+const\s+struct\s+clm_channel_range\s+(channel_ranges_[\w\d]+)\s*\[\s*\]\s*=\s*\{([^}]*)\};', re.DOTALL ) for array_name, body in pattern.findall(block): macros = [m.strip() for m in re.findall(r'RANGE_[\w\d_]+', body)] entries = [] for low, high in re.findall(r'\{\s*(\d+)\s*,\s*(\d+)\s*\}', body): entries.append({"low": int(low), "high": int(high)}) self.array_macros[array_name] = macros self.struct_entries[array_name] = entries self.logger.debug(f"解析数组 {array_name}: {len(macros)} 个宏") def get_array_name_for_range(self, range_macro): """根据 RANGE 宏推断应属于哪个数组""" match = re.match(r'RANGE_([0-9]+[A-Za-z])_([0-9]+)M_', range_macro, re.IGNORECASE) if not match: self.logger.warning(f"无法推断数组名: {range_macro}") return None band = match.group(1).lower() # '2g' bw = match.group(2) # '20' return f"channel_ranges_{band}_{bw}m" def extract_channels_from_macro(self, macro): """ 从宏字符串中提取信道范围。 Args: macro (str): 包含信道范围的宏字符串,格式应为 "_数字_数字" 形式。 Returns: tuple: 包含两个整数的元组,分别表示信道的低值和高值。如果宏格式错误,则返回 (None, None)。 """ match = re.search(r'_(\d+)_(\d+)$', macro) if match: low = int(match.group(1)) high = int(match.group(2)) return low, high self.logger.warning(f"宏格式错误,无法提取信道: {macro}") return None, None def validate_and_repair(self): """确保每个 used_range 都在正确的数组中""" modified = False changes = [] for range_macro in self.used_ranges: array_name = self.get_array_name_for_range(range_macro) if not array_name: self.logger.warning(f"无法识别数组型,跳过: {range_macro}") continue if array_name not in self.array_macros: self.logger.info(f"创建新数组: {array_name}") self.array_macros[array_name] = [] self.struct_entries[array_name] = [] if range_macro not in self.array_macros[array_name]: low, high = self.extract_channels_from_macro(range_macro) if low is not None and high is not None: self.array_macros[array_name].append(range_macro) self.struct_entries[array_name].append({"low": low, "high": high}) changes.append(f"添加: {range_macro} → {{{low}, {high}}} 到 {array_name}") self.logger.info(f"将添加: {range_macro} → {{{low}, {high}}} 到 {array_name}") modified = True else: self.logger.warning(f"无法解析信道范围: {range_macro}") if modified and not self.dry_run: self._write_back_in_block() self.logger.info("C 文件已更新") elif modified and self.dry_run: self.logger.info("DRY-RUN MODE: 有变更但不会写入文件") else: self.logger.info("所有 RANGE 已存在,无需修改") return modified def _infer_array_from_enum(self, enum_decl): """ 从枚举声明中推断数组名称。 Args: enum_decl (str): 枚举声明字符串。 Returns: Optional[str]: 如果匹配到枚举声明,则返回推断出的数组名称;否则返回None。 """ match = re.search(r'enum\s+range_([a-z\d_]+)', enum_decl) if match: return f"channel_ranges_{match.group(1)}" return None def _format_array_body(self, macros, structs, indent=" "): """ 将宏定义和结构体信息格式化为字符串。 Args: macros (list): 宏定义列表。 structs (list): 结构体信息列表,每个元素是一个包含'low'和'high'键的字典。 indent (str, optional): 缩进字符串。默认为" "。 Returns: str: 格式化后的字符串。 """ lines = [] for i in range(len(macros)): line = f"{indent}{{ {structs[i]['low']}, {structs[i]['high']} }}, /* {macros[i]} */" lines.append(line) return "\n".join(lines) def _write_back_in_block(self): """ 安全地一次性更新 C 文件中的数组和枚举定义。 如果是 dry_run 模式,则不进行任何文件 I/O 操作(包括备份和写入)。 """ if self.dry_run: self.logger.info("DRY-RUN: 跳过写入文件(包括备份)") return try: content = self.c_file_path.read_text(encoding='utf-8') start_idx = content.find(self.start_marker) end_idx = content.find(self.end_marker) + len(self.end_marker) if start_idx == -1 or end_idx == -1: raise ValueError("未找到 CHANNEL RANGES 标记块") header = content[:start_idx] footer = content[end_idx:] block = content[start_idx:end_idx] new_block = block # === 更新数组定义 === array_pattern = re.compile( r'(static\s+const\s+struct\s+clm_channel_range\s+(channel_ranges_[\w\d]+)\s*\[\s*\]\s*=\s*\{)([^}]*)\};', re.DOTALL ) for match in array_pattern.finditer(block): array_name = match.group(2) if array_name not in self.array_macros: continue macros = self.array_macros[array_name] structs = self.struct_entries[array_name] formatted_body = self._format_array_body(macros, structs) old_decl = match.group(0) new_decl = f"{match.group(1)}\n{formatted_body}\n}};" new_block = new_block.replace(old_decl, new_decl) # === 更新 enum 定义 === enum_pattern = re.compile(r'(enum\s+range_[\w\d_]+\s*\{)([^}]*)\}(;)', re.DOTALL) final_block = new_block for match in enum_pattern.finditer(new_block): enum_body = match.group(2).strip() existing_macros = dict(re.findall(r'(RANGE_[\w\d_]+)\s*=\s*(\d+)', enum_body)) array_name = self._infer_array_from_enum(match.group(0)) if not array_name or array_name not in self.array_macros: continue expected_macros = self.array_macros[array_name] current_ids = [int(v) for v in existing_macros.values()] next_id = max(current_ids) + 1 if current_ids else 0 missing_macros = [m for m in expected_macros if m not in existing_macros] if not missing_macros: continue insert_lines = [f" {macro} = {next_id + i}," for i, macro in enumerate(missing_macros)] to_insert = "\n" + "\n".join(insert_lines) if enum_body.endswith(","): to_insert = "," + to_insert final_block = final_block[:match.end(2)] + to_insert + final_block[match.end(2):] # === 执行 I/O:仅在此处进行文件操作 === backup_path = self.c_file_path.with_suffix('.c.bak') copy2(self.c_file_path, backup_path) self.logger.info(f"已备份 → {backup_path}") self.c_file_path.write_text(header + final_block + footer, encoding='utf-8') self.logger.info(f"已保存: {self.c_file_path}") except Exception as e: self.logger.error(f"写回文件失败: {e}") raise def run(self): self.logger.info("开始同步 CLM RANGE 定义...") try: self.load_manifest() self.parse_c_arrays() was_modified = self.validate_and_repair() # 🔍 根据 dry_run 和是否需要修改,输出不同信息 if was_modified: if self.dry_run: self.logger.info("🟡 预览模式:检测到变更,但不会写入文件") else: self.logger.info("✅ 同步完成:已成功更新 C 文件") else: self.logger.info("🟢 所有 RANGE 已存在,无需修改") return was_modified except Exception as e: self.logger.error(f"❌ 同步失败: {e}") raise def main(): # ✅ 配置 logging:同时输出到 控制台 和 文件 logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s', handlers=[ logging.FileHandler(LOG_FILE, encoding='utf-8'), # 写入日志文件 logging.StreamHandler(sys.stdout) # 输出到屏幕 ], force=True # 允许重复运行(如 PyCharm 中多次 Run) ) logger = logging.getLogger(__name__) # === 固定配置 === manifest_path = "../output/generated_ranges_manifest.json" c_file_path = "../input/wlc_clm_data_6726b0.c" dry_run = False log_level = "INFO" # 设置运行时日志级别 logging.getLogger().setLevel(log_level) print(f"📌 开始同步 RANGE 定义...") print(f"📊 manifest 文件: {manifest_path}") print(f"📄 C 源文件: {c_file_path}") if dry_run: print("🟡 启用 dry-run 模式:仅预览变更,不修改文件") try: sync = CLMRangeSynchronizer( manifest_path=manifest_path, c_file_path=c_file_path, dry_run=dry_run ) sync.run() print("✅ 同步完成!") print(f"📄 详细日志已保存至: {LOG_FILE}") # 👈 提示用户日志位置 except FileNotFoundError as e: logger.error(f"文件未找到: {e}") print("❌ 请检查文件路径是否正确。") sys.exit(1) except PermissionError as e: logger.error(f"权限错误: {e}") print("❌ 无法读取或写入文件,请检查权限。") sys.exit(1) except Exception as e: logger.error(f"程序异常退出: {e}", exc_info=True) sys.exit(1) if __name__ == '__main__': main() 我发现执行完之后,// === START CHANNEL RANGES === /** 2.4G 20M channel ranges used in locales and restricted sets */ static const struct clm_channel_range channel_ranges_2g_20m[] = { { 1, 1}, { 1, 2}, { 1, 11}, { 1, 13}, { 1, 14}, { 2, 2}, { 2, 7}, { 2, 10}, { 3, 3}, { 3, 9}, { 3, 10}, { 4, 4}, { 4, 8}, { 5, 7}, { 8, 8}, { 9, 9}, { 10, 10}, { 11, 11}, { 12, 12}, { 12, 13}, { 13, 13}, { 14, 14}, }; /** Indices for 2.4G 20M channel ranges */ enum range_2g_20m { RANGE_2G_20M_1_1 = 0, RANGE_2G_20M_1_2 = 1, RANGE_2G_20M_1_11 = 2, RANGE_2G_20M_1_13 = 3, RANGE_2G_20M_1_14 = 4, RANGE_2G_20M_2_2 = 5, RANGE_2G_20M_2_7 = 6, RANGE_2G_20M_2_10 = 7, RANGE_2G_20M_3_3 = 8, RANGE_2G_20M_3_9 = 9, RANGE_2G_20M_3_10 = 10, RANGE_2G_20M_4_4 = 11, RANGE_2G_20M_4_8 = 12, RANGE_2G_20M_5_7 = 13, RANGE_2G_20M_8_8 = 14, RANGE_2G_20M_9_9 = 15, RANGE_2G_20M_10_10 = 16, RANGE_2G_20M_11_11 = 17, RANGE_2G_20M_12_12 = 18, RANGE_2G_20M_12_13 = 19, RANGE_2G_20M_13_13 = 20, RANGE_2G_20M_14_14 = 21, }; /** 2.4G 40M channel ranges used in locales and restricted sets */ static const struct clm_channel_range channel_ranges_2g_40m[] = { { 3, 3}, { 3, 11}, { 4, 4}, { 4, 5}, { 5, 5}, { 5, 6}, { 5, 7}, { 6, 6}, { 6, 7}, { 7, 7}, { 7, 8}, { 8, 8}, { 9, 9}, { 10, 10}, { 11, 11}, }; /** Indices for 2.4G 40M channel ranges */ enum range_2g_40m { RANGE_2G_40M_3_3 = 0, RANGE_2G_40M_3_11 = 1, RANGE_2G_40M_4_4 = 2, RANGE_2G_40M_4_5 = 3, RANGE_2G_40M_5_5 = 4, RANGE_2G_40M_5_6 = 5, RANGE_2G_40M_5_7 = 6, RANGE_2G_40M_6_6 = 7, RANGE_2G_40M_6_7 = 8, RANGE_2G_40M_7_7 = 9, RANGE_2G_40M_7_8 = 10, RANGE_2G_40M_8_8 = 11, RANGE_2G_40M_9_9 = 12, RANGE_2G_40M_10_10 = 13, RANGE_2G_40M_11_11 = 14, , RANGE_2G_40M_4_8 = 15,};只插入了一个RANGE_2G_40M_4_8 = 15,并且还没有在channel_ranges_2g_40m[]里面增加{15 15},但是看日志写的C:\Users\admin\PyCharmMiscProject\.venv\Scripts\python.exe F:\issue\channel\range_sync.py 📌 开始同步 RANGE 定义... 📊 manifest 文件: ../output/generated_ranges_manifest.json 📄 C 源文件: ../input/wlc_clm_data_6726b0.c 2025-10-15 20:32:52,502 [INFO] __main__: 开始同步 CLM RANGE 定义... 2025-10-15 20:32:52,503 [INFO] __main__: 已加载 7 个有效 RANGE 宏 2025-10-15 20:32:52,508 [INFO] __main__: 创建新数组: channel_ranges_2g_20m 2025-10-15 20:32:52,508 [INFO] __main__: 将添加: RANGE_2G_20M_11_11 → {11, 11} 到 channel_ranges_2g_20m 2025-10-15 20:32:52,508 [INFO] __main__: 将添加: RANGE_2G_20M_1_1 → {1, 1} 到 channel_ranges_2g_20m 2025-10-15 20:32:52,508 [INFO] __main__: 将添加: RANGE_2G_20M_1_11 → {1, 11} 到 channel_ranges_2g_20m 2025-10-15 20:32:52,508 [INFO] __main__: 将添加: RANGE_2G_20M_2_10 → {2, 10} 到 channel_ranges_2g_20m 2025-10-15 20:32:52,508 [INFO] __main__: 创建新数组: channel_ranges_2g_40m 2025-10-15 20:32:52,510 [INFO] __main__: 将添加: RANGE_2G_40M_3_3 → {3, 3} 到 channel_ranges_2g_40m 2025-10-15 20:32:52,510 [INFO] __main__: 将添加: RANGE_2G_40M_4_8 → {4, 8} 到 channel_ranges_2g_40m 2025-10-15 20:32:52,510 [INFO] __main__: 将添加: RANGE_2G_40M_9_9 → {9, 9} 到 channel_ranges_2g_40m 2025-10-15 20:32:52,518 [INFO] __main__: 已备份 → ..\input\wlc_clm_data_6726b0.c.bak 2025-10-15 20:32:52,523 [INFO] __main__: 已保存: ..\input\wlc_clm_data_6726b0.c 2025-10-15 20:32:52,523 [INFO] __main__: C 文件已更新 2025-10-15 20:32:52,523 [INFO] __main__: ✅ 同步完成:已成功更新 C 文件 ✅ 同步完成! 📄 详细日志已保存至: F:\issue\output\log\range_sync_20251015_203252.log 进程已结束,退出代码为 0 我很蒙
最新发布
10-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值