inih (INI Not Invented Here) เป็นตัวแยกวิเคราะห์ไฟล์ .INI ธรรมดาที่เขียนด้วยภาษาซี มีโค้ดเพียงไม่กี่หน้า และได้รับการออกแบบให้มี ขนาดเล็กและเรียบง่าย ดังนั้นจึงเหมาะสำหรับระบบฝังตัว นอกจากนี้ยังเข้ากันได้กับรูปแบบ ConfigParser ของไฟล์ .INI ของ Python ไม่มากก็น้อย รวมถึงไวยากรณ์หลายบรรทัดสไตล์ RFC 822 และรายการ name: value
หากต้องการใช้งาน เพียงให้ไฟล์ INI แก่ ini_parse() จากนั้นมันจะโทรกลับสำหรับทุกคู่ name=value ที่แยกวิเคราะห์ โดยให้สตริงสำหรับส่วน ชื่อ และค่า ที่ทำในลักษณะนี้ ("รูปแบบ SAX") เนื่องจากทำงานได้ดีบนระบบฝังตัวที่มีหน่วยความจำต่ำ แต่ยังเป็นเพราะทำให้มีการใช้งาน KISS อีกด้วย
คุณยังสามารถเรียก ini_parse_file() เพื่อแยกวิเคราะห์โดยตรงจากออบเจ็กต์ FILE* , ini_parse_string() เพื่อแยกวิเคราะห์ข้อมูลจากสตริง หรือ ini_parse_stream() เพื่อแยกวิเคราะห์โดยใช้ฟังก์ชันตัวอ่านสไตล์ fgets แบบกำหนดเองสำหรับ I/O แบบกำหนดเอง
ดาวน์โหลดรุ่น ค้นหาแหล่งที่มา หรืออ่านเกี่ยวกับวิธีใช้ inih ในรูปแบบ DRY ด้วย X-Macros
คุณสามารถควบคุมแง่มุมต่างๆ ของ inih ได้โดยใช้ตัวประมวลผลล่วงหน้ากำหนด:
-DINI_ALLOW_MULTILINE=0-DINI_ALLOW_BOM=0; อักขระ. หากต้องการปิดใช้งาน ให้เพิ่ม -DINI_ALLOW_INLINE_COMMENTS=0 คุณยังสามารถระบุอักขระที่จะเริ่มต้นความคิดเห็นแบบอินไลน์โดยใช้ INI_INLINE_COMMENT_PREFIXES; และ # เพื่อเริ่มความคิดเห็นที่ต้นบรรทัด คุณสามารถแทนที่สิ่งนี้ได้โดยเปลี่ยน INI_START_COMMENT_PREFIXES= หรือ : ในบรรทัด) เป็นข้อผิดพลาด หากต้องการอนุญาตชื่อที่ไม่มีค่า ให้เพิ่ม -DINI_ALLOW_NO_VALUE=1 และ inih จะเรียกใช้ฟังก์ชันตัวจัดการของคุณโดยตั้งค่าเป็น NULL-DINI_STOP_ON_FIRST_ERROR=1ini_handler จะไม่ได้รับหมายเลขบรรทัดเป็นพารามิเตอร์ หากคุณต้องการสิ่งนั้น ให้เพิ่ม -DINI_HANDLER_LINENO=1name=value หากต้องการตรวจหาส่วนใหม่ (เช่น ไฟล์ INI มีหลายส่วนที่มีชื่อเดียวกัน) ให้เพิ่ม -DINI_CALL_HANDLER_ON_NEW_SECTION=1 จากนั้นฟังก์ชันตัวจัดการของคุณจะถูกเรียกทุกครั้งที่พบส่วนใหม่ โดยตั้ง section เป็นชื่อส่วนใหม่ แต่ตั้ง name และ value เป็น NULLmalloc แทน ให้ระบุ -DINI_USE_STACK=0-DINI_MAX_LINE=1000 โปรดทราบว่า INI_MAX_LINE จะต้องมากกว่าบรรทัดที่ยาวที่สุด 3 (เนื่องจาก r , n และ NUL)INI_INITIAL_ALLOC ระบุขนาด malloc เริ่มต้นเมื่อใช้ฮีป มีค่าเริ่มต้นอยู่ที่ 200 ไบต์-DINI_USE_STACK=0 ) inih จะจัดสรรบัฟเฟอร์ขนาดคงที่จำนวน INI_INITIAL_ALLOC ไบต์ หากต้องการอนุญาตให้ขยายเป็น INI_MAX_LINE ไบต์ หรือเพิ่มขึ้นเป็นสองเท่าหากจำเป็น ให้ตั้งค่า -DINI_ALLOW_REALLOC=1malloc , free และ realloc ของไลบรารีมาตรฐานจะถูกใช้ หากต้องการใช้ตัวจัดสรรที่กำหนดเอง ให้ระบุ -DINI_CUSTOM_ALLOCATOR=1 (และ -DINI_USE_STACK=0 ) คุณต้องกำหนดและลิงก์ฟังก์ชันชื่อ ini_malloc , ini_free และ (หากตั้งค่า INI_ALLOW_REALLOC ) ini_realloc ซึ่งต้องมีลายเซ็นเดียวกันกับฟังก์ชันการจัดสรรหน่วยความจำ stdlib.h #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../ini.h"
typedef struct
{
int version ;
const char * name ;
const char * email ;
} configuration ;
static int handler ( void * user , const char * section , const char * name ,
const char * value )
{
configuration * pconfig = ( configuration * ) user ;
#define MATCH ( s , n ) strcmp(section, s) == 0 && strcmp(name, n) == 0
if ( MATCH ( "protocol" , "version" )) {
pconfig -> version = atoi ( value );
} else if ( MATCH ( "user" , "name" )) {
pconfig -> name = strdup ( value );
} else if ( MATCH ( "user" , "email" )) {
pconfig -> email = strdup ( value );
} else {
return 0 ; /* unknown section/name, error */
}
return 1 ;
}
int main ( int argc , char * argv [])
{
configuration config ;
if ( ini_parse ( "test.ini" , handler , & config ) < 0 ) {
printf ( "Can't load 'test.ini'n" );
return 1 ;
}
printf ( "Config loaded from 'test.ini': version=%d, name=%s, email=%sn" ,
config . version , config . name , config . email );
return 0 ;
} หากคุณใช้ C++ และ STL ก็ยังมีคลาส INIReader ที่ใช้งานง่ายซึ่งเก็บค่าไว้ใน map และให้คุณ Get() ค่าเหล่านั้น:
# include < iostream >
# include " INIReader.h "
int main ()
{
INIReader reader ( " ../examples/test.ini " );
if (reader. ParseError () < 0 ) {
std::cout << " Can't load 'test.ini' n " ;
return 1 ;
}
std::cout << " Config loaded from 'test.ini': version= "
<< reader. GetInteger ( " protocol " , " version " , - 1 ) << " , name= "
<< reader. Get ( " user " , " name " , " UNKNOWN " ) << " , email= "
<< reader. Get ( " user " , " email " , " UNKNOWN " ) << " , pi= "
<< reader. GetReal ( " user " , " pi " , - 1 ) << " , active= "
<< reader. GetBoolean ( " user " , " active " , true ) << " n " ;
return 0 ;
} C ++ API แบบง่ายนี้ทำงานได้ดี แต่ก็ไม่ได้เต็มประสิทธิภาพมากนัก ฉันไม่ได้วางแผนที่จะทำงานกับ C++ API มากขึ้นในขณะนี้ ดังนั้นหากคุณต้องการประสิทธิภาพเพิ่มขึ้นอีกเล็กน้อย (เช่น ฟังก์ชัน GetSections() และ GetFields() ) โปรดดูทางแยกเหล่านี้:
ความแตกต่างบางประการระหว่างโมดูลไลบรารีมาตรฐาน ConfigParser ของ inih และ Python:
_wfopen() เพื่อเปิดไฟล์ จากนั้นจึง ini_parse_file() เพื่อแยกวิเคราะห์ inih ไม่รวมการจัดการ wchar_t หรือ Unicode meson.build ไม่จำเป็นต้องใช้หรือคอมไพล์ inih จุดประสงค์หลักคือเพื่อการแจกแจง-Ddefault_library=static static libraries ถูกสร้างขึ้น-Ddistro_install=false ไลบรารี่ ส่วนหัวและไฟล์ pkg-config จะไม่ถูกติดตั้ง-Dwith_INIReader=false คุณสามารถปิดการใช้งานการสร้างไลบรารี C++ ได้distro_install ถูกตั้งค่าเป็น trueinih และ INIReaderinih_dep และ INIReader_dep ได้ คุณอาจต้องการตั้งค่า default_library=static และ distro_install=false สำหรับโปรเจ็กต์ย่อย Wrap อย่างเป็นทางการมีให้ใน WrapDBversion : '<version_as_int>', หลังแท็ก license ในฟังก์ชัน project() และ version : meson.project_version(), หลังแท็ก soversion ในฟังก์ชัน library() ทั้งสอง inih สามารถใช้งานได้ง่ายในโปรเจ็กต์ tipi.build เพียงเพิ่มรายการต่อไปนี้ใน .tipi/deps ของคุณ (แทนที่ r56 ด้วยแท็กเวอร์ชันล่าสุด):
{
"benhoyt/inih" : { "@" : " r56 " }
}เส้นทางรวมที่จำเป็นในโครงการของคุณคือ:
#include <ini.h> คุณสามารถสร้างและติดตั้ง inih โดยใช้ตัวจัดการการพึ่งพา vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install inih
พอร์ต inih ใน vcpkg ได้รับการปรับปรุงให้ทันสมัยอยู่เสมอโดยสมาชิกทีม Microsoft และผู้สนับสนุนชุมชน หากเวอร์ชันล้าสมัย โปรดสร้างปัญหาหรือดึงคำขอบนที่เก็บ vcpkg