author: Bertrand Russell
这种双引号前后一闭合,管你多长的字符通通放一行,中间还可能插入各种恶心转义字符例如\\n
,可读性真的很差。python/node.js/ruby/java的yaml库都翻了遍,python比较接近*1
。各种库对输入的parse/load都很强大,但是反过来输出yaml时,就开始变成各种反人类亲机器的文件格式,完全抛弃yaml的可读性。
求推荐yaml库,可通过简单的设置或者扩展,自定义长字符串以区块的形式的输出,多于80列则自动换行,如下
title: THE PROBLEMS OF PHILOSOPHY
author: Bertrand Russellpreface:In the following pages I have confined myself in the main to those problems of
或者是扩展性比较高的格式化输出工具。
在go语言中使用viper之类的库很方便的处理yaml配置文件,但是在c语言中就比较麻烦,经过一番思索和借助强大的github,发现了一个libyaml c库,但是网上的例子都比较麻烦,而且比较繁琐,就想法作了一个相对比较容易配置的解析应用,可以简单地类似viper 的模式进行配置实现不同的配置文件读取。如你的配置文件很复杂请按格式修改KeyValue 全局变量,欢迎大家一起完善
库请自行下载 GitHub - yaml/libyaml: Canonical source repository for LibYAML
直接上代码
yaml示例文件
%YAML 1.1
---
mqtt:
subtopic: "Control/#"
pubtopic: "bbt"
qos: 1
serveraddress: "tcp://192.168.0.25:1883"
clientid: "kvm_test"
writelog: false
writetodisk: false
outputfile: "./receivedMessages.txt"
hearttime: 30
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
/************************/
/* Minimum YAML version */
/************************/
#define YAML_VERSION_MAJOR 1
#define YAML_VERSION_MINOR 1
#define STRUCT_TYPE_NAME 100
#define INT_TYPE_NAME 101
#define STRING_TYPE_NAME 102
#define BOOL_TYPE_NAME 103
#define FLOAT_TYPE_NAME 104
#define MAP_TYPE_NAME 105
#define LIST_TYPE_NAME 106
typedef struct{
char *key
void *value
int valuetype
char *parent
}KeyValue,*pKeyValue
#ifdef __cplusplus
}
#endif
#endif
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
typedef struct {
char *SUBTOPIC//string `yaml:"subtopic" mapstructure:"subtopic"` //"topic1"
char *PUBTOPIC//string `yaml:"pubtopic" mapstructure:"pubtopic"`
int QOS//byte `yaml:"qos" mapstructure:"qos"` //1
char *SERVERADDRESS//string `yaml:"serveraddress" mapstructure:"serveraddress"` //= "tcp://mosquitto:1883"
char *CLIENTID//string `yaml:"clientid" mapstructure:"clientid"` //= "mqtt_subscriber"
int HEARTTIME//int `yaml:"hearttime" mapstructure:"hearttime"`
// CommandLocalPath string `yam:"commanlocalpath"`
}mqttSection,*pmqttSection
typedef struct {
mqttSection Mqtt// `yaml:"mqtt" mapstructure:"mqtt"`
// KVM kvmSection `yaml:"kvm" mapstructure:"kvm"`
}ConfigT
ConfigT config
static KeyValue webrtcconfig[]={
{"mqtt",&config,STRUCT_TYPE_NAME,NULL},
{"subtopic",&(config.Mqtt.SUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"pubtopic",&(config.Mqtt.PUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"qos",&(config.Mqtt.QOS),INT_TYPE_NAME,"mqtt"},
{"serveraddress",&(config.Mqtt.SERVERADDRESS),STRING_TYPE_NAME,"mqtt"},
{"clientid",&(config.Mqtt.CLIENTID),STRING_TYPE_NAME,"mqtt"},
{"hearttime",&(config.Mqtt.HEARTTIME),INT_TYPE_NAME,"mqtt"},
{NULL,NULL,0,NULL},
}
int printConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1
printf("mqtt:r ")
if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("subtopic: %sr ",pconfig->Mqtt.SUBTOPIC)}
if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("pubtopic: %sr ",pconfig->Mqtt.PUBTOPIC)}
printf("qos: %dr ",config.Mqtt.QOS)
if(pconfig->Mqtt.SERVERADDRESS!=NULL) {printf("serveraddress: %sr ",pconfig->Mqtt.SERVERADDRESS)}
if(pconfig->Mqtt.CLIENTID!=NULL) {printf("clientid: %sr ",pconfig->Mqtt.CLIENTID)}
printf("hearttime: %dr ",config.Mqtt.HEARTTIME)
}
int freeConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1
if(pconfig->Mqtt.SERVERADDRESS!=NULL) {free(pconfig->Mqtt.SERVERADDRESS)}
if(pconfig->Mqtt.CLIENTID!=NULL) {free(pconfig->Mqtt.CLIENTID)}
if(pconfig->Mqtt.SUBTOPIC!=NULL) {free(pconfig->Mqtt.SUBTOPIC)}
}
char currentkey[100]
void getvalue(yaml_event_t event,pKeyValue *ppconfigs){
char *value = (char *)event.data.scalar.value
pKeyValue pconfig=*ppconfigs
char *pstringname
while(pconfig->key!=NULL){
if(currentkey[0]!=0){
if(!strcmp(currentkey,pconfig->key))
{
switch(pconfig->valuetype){
case STRING_TYPE_NAME:
pstringname=strdup(value)
printf("get string value %sr ",pstringname)
*((char**)pconfig->value)=pstringname
memset(currentkey, 0, sizeof(currentkey))
break
case INT_TYPE_NAME:
*((int*)(pconfig->value))=atoi(value)
memset(currentkey, 0, sizeof(currentkey))
break
case BOOL_TYPE_NAME:
if(!strcmp(value,"true")) *((bool*)(pconfig->value))=true
else *((bool*)(pconfig->value))=false
memset(currentkey, 0, sizeof(currentkey))
break
case FLOAT_TYPE_NAME:
*((float*)(pconfig->value))=atof(value)
memset(currentkey, 0, sizeof(currentkey))
break
case STRUCT_TYPE_NAME:
case MAP_TYPE_NAME:
case LIST_TYPE_NAME:
memset(currentkey, 0, sizeof(currentkey))
strncpy(currentkey,value,strlen(value))
break
default:
break
}
break
}
//continue
}else{
if(!strcmp(value,pconfig->key)){
strncpy(currentkey,pconfig->key,strlen(pconfig->key))
break
}
}
pconfig++
}
}
int Load_YAML_Config( char *yaml_file, KeyValue *(configs[]) )
{
struct stat filecheck
yaml_parser_t parser
yaml_event_t event
bool done = 0
unsigned char type = 0
unsigned char sub_type = 0
if (stat(yaml_file, &filecheck) != false )
{
printf("[%s, line %d] Cannot open configuration file '%s'! %s", __FILE__, __LINE__, yaml_file, strerror(errno) )
return -1
}
FILE *fh = fopen(yaml_file, "r")
if (!yaml_parser_initialize(&parser))
{
printf("[%s, line %d] Failed to initialize the libyaml parser. Abort!", __FILE__, __LINE__)
return -1
}
if (fh == NULL)
{
printf("[%s, line %d] Failed to open the configuration file '%s' Abort!", __FILE__, __LINE__, yaml_file)
return -1
}
memset(currentkey, 0, sizeof(currentkey))
/* Set input file */
yaml_parser_set_input_file(&parser, fh)
while(!done)
{
if (!yaml_parser_parse(&parser, &event))
{
/* Useful YAML vars: parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1 */
printf( "[%s, line %d] libyam parse error at line %ld in '%s'", __FILE__, __LINE__, parser.problem_mark.line+1, yaml_file)
}
if ( event.type == YAML_DOCUMENT_START_EVENT )
{
//yaml file first line is version
//%YAML 1.1
//---
yaml_version_directive_t *ver = event.data.document_start.version_directive
if ( ver == NULL )
{
printf( "[%s, line %d] Invalid configuration file. Configuration must start with "%%YAML 1.1"", __FILE__, __LINE__)
}
int major = ver->major
int minor = ver->minor
if (! (major == YAML_VERSION_MAJOR &&minor == YAML_VERSION_MINOR) )
{
printf( "[%s, line %d] Configuration has a invalid YAML version. Must be 1.1 or above", __FILE__, __LINE__)
return -1
}
}
else if ( event.type == YAML_STREAM_END_EVENT )
{
done = true
}
else if ( event.type == YAML_MAPPING_END_EVENT )
{
sub_type = 0
}
else if ( event.type == YAML_SCALAR_EVENT )
{
getvalue(event,configs)
}
}
return 0
}
int main(int argc, char *argv[]){
pKeyValue pconfig=&webrtcconfig[0]
Load_YAML_Config("../../etc/kvmagent.yml",&pconfig)
printConfig(&config)
freeConfig(&config)
}
NetBeans IDE 是由 Sun 公司推出一款优秀、免费、开源的集成开发工具,我们可以通过其开发专业的 Java 桌面、Web、企业以及移动应用程序。它同时支持 C/C++ 甚至是 Ruby 语言的开发,并且可以运行在多个操作系统之上,包括 Windows, Linux, Mac OSX 和 Solaris。最新发布的 NetBeans IDE 6.0 版本拥有诸多引人瞩目的新特性,包括完全重新打造的代码编辑器,众多语言的支持,简易高效的开发方式以及轻松快捷的安装和配置。
IDE :
人性化的下载和安装方式:NetBeans 6.0 的 Java SE 版本仅需 21 MB!
插件管理器:用它可以在不同版本之间轻松转换,而不必下载新的安装文件。
标准化的项目构成:NetBeans 6.0 的 Java 项目默认使用 Ant 1.7,同时支持 Maven。
模板支持:使用 NetBeans 6.0,我们可以自行创建任何种类的应用程序模板。
工具栏拖动:自定义工具栏可以直接拖动所需的按钮到所需的位置。
可分离的面板:所有的面板都可以从 IDE 中分离出来而独立使用,通过它可以实现同时编辑多个代码文件。
项目组:将多个相关联的项目定义为一个项目组,可以方便的同时打开和关闭多个相关联的项目。
任务列表:通过注释中的 TODO 或 FIXME 建立任务列表,支持导入和导出为标准的 iCalendar 格式或直接与 bug 数据库同步。
编辑器:
语言感应编辑器:支持 Java, Ruby, C/C++, XML, HTML, RHTML, JavaScript 和 JSP 语法高亮、代码缩进、关键字匹配和自动格式化,并可扩展支持其他语言。
实时语法分析:能够即时的报告错误或提示自动修复。
重构:使用 Ctrl + R 快捷键可以直接更改变量名称,省去了查找和替换的繁琐。
自动代码补全:支持 Java, Ruby, XML, C/C++, HTML, RHTML, JSP 和 JavaScript 的自动代码补全。
自动代码生成:例如,如果使用了一个未定义的方法,IDE 会提示自动创建这个方法。
本地文件历史记录:就算没有版本控制也可以轻松恢复到本地的历史版本。
快速导航:支持快速查询某个成员或错误并定位。
完全可定制的用户界面:快捷键、工具栏按钮、界面字体均可以轻松定制。
版本控制和协同开发:
集成版本控制工具:支持快速更新、签出、对比、重命名文件和提交修改。
CVS, Subversion, Mercurial:内置 CVS 和 Subversion 支持。Mercurial 的支持可以在插件管理器中安装。
文件状态和历史记录:列出当前文件状态和所有的历史版本,可以直接比较。
基于代码行的对比查看。
远程项目共享:在网络上实时共享项目,支持远程编辑代码、调试和运行。协同开发可以在插件管理器中安装。
协同开发聊天:支持即时消息通讯。
Java SE:
JDK 多版本支持:JDK 1.1 - 1.4, 5.0 和 6
桌面应用程序开发:向导式生成桌面应用程序的基本框架。
单元测试:集成 JUnit 3 和 4。
基于 Ant 的项目构成。
可视化图形界面设计:拖拽组件式 Swing 界面开发,自动生成界面代码。
调试和性能分析。
Swing 图形用户界面设计器:
专业的 GUI 编辑器:拖拽式界面设计方式,自动对齐校正,支持提示和快捷键设置。
标准和自定义 GUI 组件:除了标准的 AWT 和 Swing 组件外,可以添加扩展自定义的组件。
支持Beans 绑定技术 (JSR 295):利用 Beans 绑定技术和 JPA 的特性可以轻松快捷的创建 Swing 桌面数据库应用程序。
支持 Swing 应用程序框架 (JSR 296)。
性能分析器:
基于任务的性能分析:自定义性能分析任务,检测 CPU、内存或其他监视参数,并可以保存结果快照。
堆走查:分析堆内容,标识不必要的引用,节约内存开销。
性能分析点:可以在代码中设置性能分析点。
标识 CPU 瓶颈:可以对特定的方法做 CPU 使用时间测试。
追踪内存使用状况。
监视线程状态。
远程性能分析。
附属性能分析:就算没有使用 IDE 运行的程序,只要用的是同一个 JDK 6,也可以做性能分析。
调试器:
表达式分析和步进:鼠标点击变量可以直接查看值。
可配置的断点。
多会话和多线程调试。
堆走查。
Java EE:
支持 Java Persistence API (JSR-220), servlets, JavaServer Pages (JSP), Enterprise JavaBeans (EJB) 和 web services 开发。
完整支持 J2EE 1.3, J2EE 1.4 和 Java EE 5 标准。
Web 和应用服务器:内置 Tomcat 6 和 GlassFish v2。支持Sun Java System Application Server 8 and 9, GlassFish v1 and v2, Apache Tomcat 4, 5 and 6, JBoss 4, BEA WebLogic 10, IBM WebSphere 6 等。
代码自动完成、模板和向导:提供蓝图、模板和向导帮助我们创建 Enterprise Java Beans (EJB 3.0), servlets, JSP pages 和 JAX-WS web services 应用。
提供 Java EE 5 资源注入元注释代码自动完成功能。
Java 持久层:支持数据库拖拽自动创建实体类,并提供模板和图形化编辑器创建和维护持久层单元。
Web 应用程序:
Visual Web JSF 开发:利用 JSF 框架进行可视化 Web 设计。
HTTP 监视器:有助于组件和 Web 应用程序的跟踪和调试。
Woodstock JSF 组件:拖拽式开发 AJAX。
标准 JSF 组件:除了提供标准的 JSF 实现组件外,还包含表格、日历、树状结构、文件上传等其他复杂组件。
JSP 开发:支持 JavaServer Pages Standard Tag Library (JSTL),Struts 1.2.9 and 1.3.x,并可以通过安装插件方式支持 Wicket 和 Spring 框架。
JavaScript 编辑器:自动识别 HTML 和 JSP 页面中的 JS 代码,并提供语法高亮、代码完成和错误检查支持。
CSS 编辑器:提供 CSS 语法高亮、代码完成、错误检查支持和代码导航。Visual CSS 编辑器提供预览功能。
数据库和数据绑定工具:自定义查询、连接、结果预览。通过数据库浏览器连接数据库,直接查看视图或数据、运行 SQL 语句。支持拖拽式数据绑定。
数 据库:内置 JavaDB (Derby), MySQL and PostgreSQL 支持,并可扩展到 Oracle, IBM DB2, Microsoft SQL Server, PointBase, Sybase, Informix, Cloudscape, InstantDB, Interbase, Firebird, FirstSQL, Mckoi SQL, HSQLDB, Hypersonic SQL 和 Micrososft Access。
Web Services:
标准化 Web 开发:支持 J2EE 1.4 and Java EE 5, including the JAX-WS 2.1, JAX-RS (JSR-311), JAX-RPC (JSR-101) web service 标准。可运行在 Sun Java System Application Server (GlassFish), Apache Tomcat, IBM WebSphere, BEA Weblogic and JBoss。
可靠、安全和可转换的 Web Services:使用在 Sun Application Server (GlassFish) 提供的 Metro 支持,构建交互的、可靠的、安全的、可转换的 Web Services。使用 Sun Java System Access Manager 构建安全的,基于身份验证的 Web Services。
同步和异步 JAX-WS 支持:NetBeans 提供可视化 JAX-WS 编辑器。
基于 SOAP 和 RESTful 的 Web Services:拖拽式 RESTful 组件自动生成所需代码,例如 Google Map, Yahoo News Search 和 StrikeIron web services。
移动 Web Service:应用 JSR-172 移动应用程序。通过无线连接桥,让 MIDlets 访问 Web Service 和其他服务器端数据。
移动开发:
手机、手持设备和机顶盒:创建、测试和调试移动信息设备简表 (MIDP) 1.0, 2.0,连接受限设备配置 (CLDC) 1.0 and 1.1 和 连接设备配置 (CDC) 应用程序。
可视化移动设计工具:利用可视化移动设计工具 v2,可以更快速的拖拽式开发图形界面,例如等待界面、登陆界面、文件浏览器、短信程序和闪屏等。同时,国际化工作也会更加方便。
移动游戏构建工具 (Mobile Game Builder):使用 MIDP 2.0 游戏 API 进行可视化开发。
模块构建系统:可以为不同平台类型、部署类型和配置加入自定义的组件。
支持 Web Services 访问。
支持 SVG:更方便的创建和编辑 SVG 图形文件 (JSR-226)。
集 成工具:JMUnit testing, MIDlet signing, 认证管理, automatic code obfuscation, integrated over-the-air (OTA) emulation, push registry emulation, WMA emulation for SMS and CBS messages, new deployment methods, and Wireless Messaging and Multimedia APIs.
Ruby:
Ruby 项目:支持Ruby 文件,RSpec 标准定义文件和 YAML 文件。实时代码解析。
Ruby on Rails 项目:支持 Rake 和数据库移植。通过图形向导生成代码。
Ruby and Rails 调试器。
Ruby Gems 安装管理器。
C/C++:
C/C++ 项目和模板。
源代码编辑器:代码自动高亮、自动完成、自动格式化、匹配、折叠。
调试器:完美集成 GNU gdb 调试器。
编译器配置。
Makefile 支持。
类继承关系浏览器。
文件导航。
UML:
正向和反向工程:支持 UML 模型图生成 Java 代码。
支 持8种 UML 图:Activity diagram, Class diagram, Collaboration diagram, Component diagram, Deployment diagram, Sequence diagram, State diagram 和 Use Case diagram
自定义代码生成模式。
集成 UML 工具:支持 Telelogic DOORS 导入,支持导出 Javadoc 样式报告。
EJB 1.1, EJB 2.0 和 Gang of Four 设计模式。
SOA:
Web Services:支持文件、HTTP 和 JMS 绑定组件。
可视化 BPEL 设计工具。
可视化 XSLT 设计工具。
XML 视图向导和可视化 WSDL 编辑器。
平台:
一般桌面应用程序:提供众多基础组件,例如:窗口管理、菜单、设置、存储、更新向导和文件访问等。
富客户端开发。
模块化:动态模块装载。
一致性:一次编写、到处运行,轻松实现跨平台应用。
新的 API:Visual Library API, NetBeans Preferences API, Lexer API。