कंफ़ेद्दी - आपकी परियोजना का सरल और त्वरित विन्यास

यदि आप किसी प्रोजेक्ट को औसत से थोड़ा अधिक लिखते हैं, तो एक नियम के रूप में आपको सेटिंग्स और कॉन्फ़िगरेशन का सामना करना पड़ता है। काफी कुछ सी / सी ++ समाधान हैं, मैं आपको मेल @ आरयू कंपनी से एक नहीं बल्कि सरल और सुंदर समाधान के बारे में बताना चाहता हूं, जिसका उपयोग मैंने अपनी परियोजना में किया था

मैंने स्वयं विभिन्न कॉन्फ़िगर पार्सर का उपयोग किया, हाल ही के प्रोजेक्ट्स में मैंने re2c का उपयोग किया (यह कॉन्फिगर नगणक्स कॉन्फिगर के समान था)। Re2c में कैंडी के साथ सामान्य रूप से थोड़ा सा है - यह कोड पीढ़ी है:
कोई कॉन्फ़िगरेशन फ़ाइल या संरचना को एन्कोडेड करने की आवश्यकता नहीं है; कंफ़ेद्दी जादूगर आपके लिए सब कुछ करेगा।

दुर्भाग्य से, कोई प्रलेखन नहीं है, अन्यथा यह लेख नहीं होता। उन लोगों के लिए, हम पूछना ...


स्रोत स्थापित करें
c github github.com/mailru/confetti
मूल आवश्यकता YACC की स्थापना है।

उदाहरण फ़ोल्डर में एक उपयोग उदाहरण है। उदाहरण का उपयोग करना और कॉन्फ़िगरेशन का निर्माण करना सहज है। पूरे बिंदु कई चरणों का अनुक्रमिक निष्पादन है:
// 1. example.cfgtmpl:
../confetti -i example.cfgtmpl -n my_product -f my_product.cfg

// 2. h :
../confetti -i example.cfgtmpl -n my_product -h my_product_cfg.h
../confetti -i example.cfgtmpl -n my_product -c my_product_cfg.c
gcc -Wall -g -O0 -Werror -std=gnu99 -I. -c my_product_cfg.c

// 2. :
../confetti -i example.cfgtmpl -H prscfg.h
../confetti -i example.cfgtmpl -p prscfg.c
gcc -Wall -g -O0 -Werror -std=gnu99 -I. -c prscfg.c

// 4.
gcc -Wall -g -O0 -Werror -std=gnu99 -I. -c example.c
gcc -o example example.o my_product_cfg.o prscfg.o


यदि आप एक उदाहरण पर विचार करते हैं, तो यह स्पष्ट होगा कि परियोजना में कैसे लागू किया जाए। मेरी परियोजना के लिए कार्यान्वयन कदम निम्नलिखित हैं।

1. अपने प्रोजेक्ट के स्रोतों में एक फ़ोल्डर बनाया

सीडी config.src

2. निष्पादन योग्य फ़ाइल को फिर से लिखना

cp कंफ़ेद्दी / usr / स्थानीय / बिन

3) मेक फाइल को ठीक किया

मेरी परियोजना के संबंध में:
CONFETTI=/usr/local/bin/confetti
NAME=tarantool_proxy
CFG=tarantool_proxy.cfgtmpl

test_OBJS=tarantool_proxy_cfg.o tnt_config.o prscfg.o

all: $(NAME).cfg test

.SUFFIXES: .oc

.co:
$(CC) $(CFLAGS) $(INCLUDE) -c $<

test: $(test_OBJS)
$(CC) -o $@ $(test_OBJS) $(LIB)

tarantool_proxy: $(test_OBJS)
$(CC) -o $@ $(test_OBJS) $(LIB)

$(NAME).cfg: $(CFG)
$(CONFETTI) -i $< -n $(NAME) -f $(NAME).cfg
$(CONFETTI) -i $< -n $(NAME) -h $(NAME)_cfg.h
$(CONFETTI) -i $< -n $(NAME) -c $(NAME)_cfg.c

prscfg.c: $(CFG)
$(CONFETTI) -i $< -p $@

prscfg.h: $(CFG)
$(CONFETTI) -i $< -H $@

prscfg.c: prscfg.h $(NAME)_cfg.h

$(NAME)_cfg.c: prscfg.h $(NAME)_cfg.h

clean:
rm -f $(NAME).cfg $(NAME)_cfg.c $(NAME)_cfg.h
rm -f prscfg.c prscfg.h
rm -f test
rm *.o

install:
cp $(NAME).def.cfg ../cfg/$(NAME).cfg
cp tarantool_proxy_cfg.o ..
cp prscfg.o ..
cp *.h ..

कृपया ध्यान दें, मैंने इंस्टॉल लक्ष्य को जोड़ा है, जो उत्पन्न फाइलों को मेरे प्रोजेक्ट के स्रोतों में कॉपी करता है।

3) एक टेम्पलेट कॉन्फ़िगरेशन फ़ाइल बनाई

example.cfgtmpl से
% {} ब्लॉक में, फ़ाइल नाम को उस नाम के साथ बदलें, जो tarantool_proxy_cfg.hh में होना चाहिए:
% {
#include <prscfg.h>
#include <tarantool_proxy_cfg.h>

void out_warning ( कॉन्फेटरीरर आर, चार * प्रारूप, ... ) ;
% } :

4. मेरा अपना कॉन्फ़िगरेशन बनाया

और इसकी जाँच की:
confetti -i tarantool_proxy.cfgtmpl -n tarantool_proxy -f tarantool_proxy.cfg

Tarantool_proxy.cfgtmpl config के लापता भाग को उसके आवेदन करने के लिए जोड़ा गया:
pid = "/us/local/var/tarantool_proxy.pid"
लॉग = "/us/local/var/log/tarantool_proxy.log"

डेमॉन = 1

पूल_साइज़ = 4096

# धागों की गिनती
सूत्र =

#listen
होस्ट = "लोकलहोस्ट"
पोर्ट = 33013

# सर्वर कनेक्शन
सर्वर = [

होस्टनाम = "लोकलहोस्ट"
पोर्ट = 33013
नामस्थान = [
कुंजी = आवश्यक , आवश्यक
]
]

नामस्थान = [
प्रकार = आवश्यक , आवश्यक
]

5. कॉन्फ़िगरेशन फ़ाइल उत्पन्न करने के बाद

tarantool_proxy.cfg ने इसे डिफ़ॉल्ट कॉन्फ़िगरेशन फ़ाइल में कॉपी किया: tarantool_proxy.def.cfg और इसे आवश्यक डेटा (उनमें से कुछ) के साथ भरा:

सर्वर [को ]hostname = "host2"
सर्वर [को ]पोर्ट = 33013

सर्वर [ ]hostname = "host1"
सर्वर [ ]port = 33023


नामस्थान [ ]टाइप = "str"
नामस्थान [को ]प्रकार = "int"


सर्वर [को ]नामस्थान [को ]कुंजी = "345"
सर्वर [को ]नामस्थान [ ]कुंजी = "एबीसी"

सर्वर [ ]नामस्थान [को ]कुंजी = "xyz"
सर्वर [ ]नामस्थान [ ]कुंजी = "345"


टेम्प्लेट फ़ाइल में निर्दिष्ट मान डिफ़ॉल्ट रूप से उपयोग किए जाते हैं।
इसके अलावा, मैंने इस फ़ाइल को दोहरे के रूप में उपयोग किया, क्योंकि tarantool_proxy.cfg फ़ाइल को लगातार कंफ़ेद्दी द्वारा अधिलेखित किया जाता है

6. example.c के आधार पर एक उदाहरण फ़ाइल परीक्षक बनाया।


7. तब तक करें जब तक सब कुछ ठीक न हो जाए

यह अद्भुत होगा अगर यह पहली बार काम करता है :)

हमे ./test
==========Accepted: 11; Skipped: 0===========
pid => '/usr/local/var/tarantool_proxy.pid'
log => '/usr/local/var/log/tarantool_proxy.log'
daemon => '1'
pool_size => '4096'
threads => '4'
host => 'localhost'
port => '33013'
server[0].hostname => 'localhost'
server[0].port => '33013'
server[0].namespace[0].key => '345'
server[0].namespace[1].key => 'abc'
server[1].hostname => 'tfn24'
server[1].port => '33023'
server[1].namespace[0].key => 'xyz'
server[1].namespace[1].key => '345'
namespace[0].type => 'int'
namespace[1].type => 'str'
==========DIRECT=========
pid=/usr/local/var/tarantool_proxy.pid
daemon=1
keys
==========Destroy=========
: / ./test
==========Accepted: 11; Skipped: 0===========
pid => '/usr/local/var/tarantool_proxy.pid'
log => '/usr/local/var/log/tarantool_proxy.log'
daemon => '1'
pool_size => '4096'
threads => '4'
host => 'localhost'
port => '33013'
server[0].hostname => 'localhost'
server[0].port => '33013'
server[0].namespace[0].key => '345'
server[0].namespace[1].key => 'abc'
server[1].hostname => 'tfn24'
server[1].port => '33023'
server[1].namespace[0].key => 'xyz'
server[1].namespace[1].key => '345'
namespace[0].type => 'int'
namespace[1].type => 'str'
==========DIRECT=========
pid=/usr/local/var/tarantool_proxy.pid
daemon=1
keys
==========Destroy=========
./test
==========Accepted: 11; Skipped: 0===========
pid => '/usr/local/var/tarantool_proxy.pid'
log => '/usr/local/var/log/tarantool_proxy.log'
daemon => '1'
pool_size => '4096'
threads => '4'
host => 'localhost'
port => '33013'
server[0].hostname => 'localhost'
server[0].port => '33013'
server[0].namespace[0].key => '345'
server[0].namespace[1].key => 'abc'
server[1].hostname => 'tfn24'
server[1].port => '33023'
server[1].namespace[0].key => 'xyz'
server[1].namespace[1].key => '345'
namespace[0].type => 'int'
namespace[1].type => 'str'
==========DIRECT=========
pid=/usr/local/var/tarantool_proxy.pid
daemon=1
keys
==========Destroy=========

"प्रत्यक्ष" ब्लॉक के लिए, यह प्रत्यक्ष पहुंच का परीक्षण कर रहा है:
प्रिंटफ ( "========== DIRECT ========= \ n " ) ;
प्रिंटफ ( "pid =% s \ n " , cfg। pid ) ;
प्रिंटफ ( "डेमन =% डी \ n " , सीएफजी। डेमॉन ) ;

या सरणी तत्वों तक पहुंच:
tarantool_proxy_namespace ** it = cfg। नाम स्थान ;
जबकि ( * इट ! = NULL ) {
प्रिंटफ ( "नाम स्थान प्रकार =% s \ n " , ( * यह ) -> प्रकार ) ;
++ यह ;
}

तो अब क्या रहता है:

  1. बनाओ स्थापित करें, जो आपकी परियोजना की निर्देशिका के लिए सभी आवश्यक फ़ाइलों को फिर से लिखेंगे।
    Config.src निर्देशिका परीक्षण साइट बनी हुई है।
  2. अपने स्वयं के प्रोजेक्ट में, #include {name} _cfg.h को शामिल करें जहां {name} वह नाम है जिसे आपने कॉन्फिगर फाइल जनरेट करते समय चुना था (मेरी परियोजना tarantool_proxy में)
  3. स्रोत कॉन्फ़िगरेशन घोषित करें और डिफ़ॉल्ट मान निर्दिष्ट करें
    tarantool_proxy cfg ;
    char * key , * value ;
    fill_default_tarantool_proxy ( & cfg ) ;

  4. कॉन्फ़िगरेशन फ़ाइल की घोषणा करें और इसे पढ़ें:
    int nAccepted , nSkipped ;
    File * fh = fopen ( फ़ाइल नाम , "आर" ) ;

    अगर ( fh ) {
    fprintf ( stderr , "फ़ाइल% s \ n नहीं खोल सका" , argv [ 1 ] ) ;
    वापसी 1 ;
    }

    useStdout = 1 ;
    parse_cfg_file_tarantool_proxy (( cfg , fh , 1 , & nAccepted , & nSkipped ) ;
    Printf ( "========== स्वीकृत:% d; स्किप्ड:% d =========== \ n " , nAccepted , nSkipped ) ;
    fclose ( fh ) ;


    यदि हम सरणियों का उपयोग करते हैं, तो हम पुनरावृत्तियों की घोषणा करते हैं:
    tarantool_proxy_iterator_t * i ;
    i = tarantool_proxy_iterator_init ( ) ;

    जबकि ( कुंजी = tarantool_proxy_iterator_next ( i , & cfg , & value ) ) ! = NULL ) {
    यदि ( मान ) {
    प्रिंटफ ( "% s => '% s' \ n " , कुंजी , मूल्य ) ;
    मुक्त ( मूल्य ) ;
    } {
    प्रिंटफ ( "% s => (नल) \ n " , कुंजी ) ;
    }
    }



या जैसा कि ऊपर बताया गया है, हम डेटा स्ट्रक्चर्स तक "डायरेक्ट" पहुंच का उपयोग करते हैं।
यह सब, परियोजना को फिर से कॉन्फ़िगर करना (कॉन्फ़िगरेशन की संरचना को बदलना) अब 5 मिनट से अधिक नहीं लेता है।

मुझे उम्मीद है कि यह किसी के लिए बहुत समय बचाएगा।
लेखक तेओदोर सिगेव के लिए धन्यवाद

Source: https://habr.com/ru/post/In127387/


All Articles