dhgdh
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
test_env.cpp
00001 /* 00002 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include <ctype.h> 00019 #include <cstdio> 00020 #include <string.h> 00021 #include "mbed.h" 00022 #include "greentea-client/test_env.h" 00023 #include "greentea-client/greentea_serial.h" 00024 00025 00026 /** 00027 * Generic test suite transport protocol keys 00028 */ 00029 const char* GREENTEA_TEST_ENV_END = "end"; 00030 const char* GREENTEA_TEST_ENV_EXIT = "__exit"; 00031 const char* GREENTEA_TEST_ENV_SYNC = "__sync"; 00032 const char* GREENTEA_TEST_ENV_TIMEOUT = "__timeout"; 00033 const char* GREENTEA_TEST_ENV_HOST_TEST_NAME = "__host_test_name"; 00034 const char* GREENTEA_TEST_ENV_HOST_TEST_VERSION = "__version"; 00035 00036 /** 00037 * Test suite success code strings 00038 */ 00039 const char* GREENTEA_TEST_ENV_SUCCESS = "success"; 00040 const char* GREENTEA_TEST_ENV_FAILURE = "failure"; 00041 00042 /** 00043 * Test case transport protocol start/finish keys 00044 */ 00045 const char* GREENTEA_TEST_ENV_TESTCASE_NAME = "__testcase_name"; 00046 const char* GREENTEA_TEST_ENV_TESTCASE_COUNT = "__testcase_count"; 00047 const char* GREENTEA_TEST_ENV_TESTCASE_START = "__testcase_start"; 00048 const char* GREENTEA_TEST_ENV_TESTCASE_FINISH = "__testcase_finish"; 00049 const char* GREENTEA_TEST_ENV_TESTCASE_SUMMARY = "__testcase_summary"; 00050 // Code Coverage (LCOV) transport protocol keys 00051 const char* GREENTEA_TEST_ENV_LCOV_START = "__coverage_start"; 00052 00053 /** 00054 * Auxilary functions 00055 */ 00056 static void greentea_notify_timeout(const int); 00057 static void greentea_notify_hosttest(const char *); 00058 static void greentea_notify_completion(const int); 00059 static void greentea_notify_version(); 00060 00061 /** \brief Handshake with host and send setup data (timeout and host test name) 00062 * \details This function will send preamble to master. 00063 * After host test name is received master will invoke host test script 00064 * and add hos test's callback handlers to main event loop 00065 * This function is blocking. 00066 */ 00067 void GREENTEA_SETUP(const int timeout, const char *host_test_name) { 00068 // Key-value protocol handshake function. Waits for {{__sync;...}} message 00069 // Sync preamble: "{{__sync;0dad4a9d-59a3-4aec-810d-d5fb09d852c1}}" 00070 // Example value of sync_uuid == "0dad4a9d-59a3-4aec-810d-d5fb09d852c1" 00071 char _key[8] = {0}; 00072 char _value[48] = {0}; 00073 while (1) { 00074 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00075 if (strcmp(_key, GREENTEA_TEST_ENV_SYNC) == 0) { 00076 // Found correct __sunc message 00077 greentea_send_kv(_key, _value); 00078 break; 00079 } 00080 } 00081 00082 greentea_notify_version(); 00083 greentea_notify_timeout(timeout); 00084 greentea_notify_hosttest(host_test_name); 00085 } 00086 00087 /** \brief Notify host (__exit message) side that test suite execution was complete 00088 * \result Test suite result 00089 * \details If __exit is not received by host side we will assume TIMEOUT 00090 */ 00091 void GREENTEA_TESTSUITE_RESULT(const int result) { 00092 greentea_notify_completion(result); 00093 } 00094 00095 /** 00096 * Test Case support 00097 */ 00098 00099 /** \brief Notify host side that test case started 00100 * \details test_case_name Test case name 00101 */ 00102 void GREENTEA_TESTCASE_START(const char *test_case_name) { 00103 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_START, test_case_name); 00104 } 00105 00106 /** \brief Notify host side that test case finished 00107 * \details test_case_name Test case name 00108 * \details result Test case result (0 -OK, non zero...) 00109 */ 00110 void GREENTEA_TESTCASE_FINISH(const char *test_case_name, const size_t passes, const size_t failed) { 00111 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_FINISH, test_case_name, passes, failed); 00112 } 00113 00114 /** 00115 ***************************************************************************** 00116 * Auxilary functions and key-value protocol support 00117 ***************************************************************************** 00118 */ 00119 00120 00121 /** 00122 ***************************************************************************** 00123 * LCOV support 00124 ***************************************************************************** 00125 */ 00126 #ifdef MBED_CFG_DEBUG_OPTIONS_COVERAGE 00127 extern "C" void __gcov_flush(void); 00128 extern bool coverage_report; 00129 00130 /** 00131 * \brief Send code coverage (gcov/LCOV) notification to master 00132 * 00133 * Generates preamble of message sent to notify host about code coverage data dump. 00134 * 00135 * This function is used by mbedOS software 00136 * (see: mbed-drivers/source/retarget.cpp file) to generate code coverage 00137 * messages to host. When code coverage feature is turned on slave will 00138 * print-out code coverage data in form of key-value protocol. 00139 * Message with code coverage data will contain message name, path to code 00140 * coverage output file host will touch and fill with code coverage binary 00141 * payload. Coverage payload is encoded as stream of ASCII coded bytes ("%02X"). 00142 * 00143 * \param path to file with code coverage payload (set by gcov instrumentation) 00144 * 00145 */ 00146 void greentea_notify_coverage_start(const char *path) { 00147 printf("{{%s;%s;", GREENTEA_TEST_ENV_LCOV_START, path); 00148 } 00149 00150 /** 00151 * \brief Sufix for code coverage message to master (closing statement) 00152 * 00153 * This function is used by mbedOS software 00154 * (see: mbed-drivers/source/retarget.cpp file) to generate code coverage 00155 * messages to host. When code coverage feature is turned on slave will 00156 * print-out code coverage data in form of key-value protocol. 00157 * Message with code coverage data will contain message name, path to code 00158 * coverage output file host will touch and fill with code coverage binary 00159 * payload. Coverage payload is encoded as stream of ASCII coded bytes ("%02X"). 00160 * 00161 * Companion function greentea_notify_coverage_start() defines code coverage message structure 00162 * 00163 */ 00164 void greentea_notify_coverage_end() { 00165 printf("}}" NL); 00166 } 00167 00168 #endif 00169 00170 /** 00171 ***************************************************************************** 00172 * Key-value protocol support 00173 ***************************************************************************** 00174 */ 00175 00176 /** 00177 * \brief Write the preamble characters to the serial port 00178 * 00179 * This function writes the preamble "{{" which is required 00180 * for key-value comunication between the target and the host. 00181 * This uses a Rawserial object, greentea_serial, which provides 00182 * a direct interface to the USBTX and USBRX serial pins and allows 00183 * the direct writing of characters using the putc() method. 00184 * This suite of functions are provided to allow for serial communication 00185 * to the host from within a thread/ISR. 00186 * 00187 */ 00188 inline void greentea_write_preamble() 00189 { 00190 greentea_serial->putc('{'); 00191 greentea_serial->putc('{'); 00192 } 00193 00194 /** 00195 * \brief Write the postamble characters to the serial port 00196 * 00197 * This function writes the postamble "{{\n" which is required 00198 * for key-value comunication between the target and the host. 00199 * This uses a Rawserial object, greentea_serial, which provides 00200 * a direct interface to the USBTX and USBRX serial pins and allows 00201 * the direct writing of characters using the putc() method. 00202 * This suite of functions are provided to allow for serial communication 00203 * to the host from within a thread/ISR. 00204 * 00205 */ 00206 inline void greentea_write_postamble() 00207 { 00208 greentea_serial->putc('}'); 00209 greentea_serial->putc('}'); 00210 greentea_serial->putc('\n'); 00211 } 00212 00213 /** 00214 * \brief Write a string to the serial port 00215 * 00216 * This function writes a '\0' terminated string from the target 00217 * to the host. It writes directly to the serial port using the 00218 * greentea_serial, Rawserial object. 00219 * 00220 * \param str - string value 00221 * 00222 */ 00223 inline void greentea_write_string(const char *str) 00224 { 00225 while (*str != '\0') { 00226 greentea_serial->putc(*str); 00227 str ++; 00228 } 00229 } 00230 00231 00232 /** 00233 * \brief Write an int to the serial port 00234 * 00235 * This function writes an integer value from the target 00236 * to the host. The integer value is converted to a string and 00237 * and then written character by character directly to the serial 00238 * port using the greentea_serial, Rawserial object. 00239 * sprintf() is used to convert the int to a string. Sprintf if 00240 * inherently thread safe so can be used. 00241 * 00242 * \param val - integer value 00243 * 00244 */ 00245 #define MAX_INT_STRING_LEN 15 00246 inline void greentea_write_int(const int val) 00247 { 00248 char intval[MAX_INT_STRING_LEN]; 00249 unsigned int i = 0; 00250 sprintf(intval, "%d", val); 00251 while (intval[i] != '\0') { 00252 greentea_serial->putc(intval[i]); 00253 i++; 00254 } 00255 } 00256 00257 /** 00258 * \brief Encapsulate and send key-value message from DUT to host 00259 * 00260 * This function uses underlying functions to write directly 00261 * to the serial port, (USBTX). This allows KVs to be used 00262 * from within interrupt context. 00263 * 00264 * \param key Message key (message/event name) 00265 * \param value Message payload, string value 00266 * 00267 */ 00268 void greentea_send_kv(const char *key, const char *val) { 00269 if (key && val) { 00270 greentea_write_preamble(); 00271 greentea_write_string(key); 00272 greentea_serial->putc(';'); 00273 greentea_write_string(val); 00274 greentea_write_postamble(); 00275 } 00276 } 00277 00278 /** 00279 * \brief Encapsulate and send key-value message from DUT to host 00280 * 00281 * This function uses underlying functions to write directly 00282 * to the serial port, (USBTX). This allows KVs to be used 00283 * from within interrupt context. 00284 * Last value is an integer to avoid integer to string conversion 00285 * made by the user. 00286 * 00287 * \param key Message key (message/event name) 00288 * \param value Message payload, integer value 00289 * 00290 */ 00291 void greentea_send_kv(const char *key, const int val) { 00292 if (key) { 00293 greentea_write_preamble(); 00294 greentea_write_string(key); 00295 greentea_serial->putc(';'); 00296 greentea_write_int(val); 00297 greentea_write_postamble(); 00298 } 00299 } 00300 00301 /** 00302 * \brief Encapsulate and send key-value-value message from DUT to host 00303 * 00304 * This function uses underlying functions to write directly 00305 * to the serial port, (USBTX). This allows KVs to be used 00306 * from within interrupt context. 00307 * Last value is an integer to avoid integer to string conversion 00308 * made by the user. 00309 * 00310 * \param key Message key (message/event name) 00311 * \param value Message payload, string value 00312 * \param result Send additional integer formatted data 00313 * 00314 */ 00315 void greentea_send_kv(const char *key, const char *val, const int result) { 00316 if (key) { 00317 greentea_write_preamble(); 00318 greentea_write_string(key); 00319 greentea_serial->putc(';'); 00320 greentea_write_string(val); 00321 greentea_serial->putc(';'); 00322 greentea_write_int(result); 00323 greentea_write_postamble(); 00324 00325 } 00326 } 00327 00328 /** 00329 * \brief Encapsulate and send key-value-value-value message from DUT to host 00330 * 00331 * This function uses underlying functions to write directly 00332 * to the serial port, (USBTX). This allows KVs to be used 00333 * from within interrupt context. 00334 * Last 2 values are integers to avoid integer to string conversion 00335 * made by the user. 00336 * 00337 * Names of the parameters: this function is used to send test case 00338 * name with number of passes and failures to host. But it can be used 00339 * to send any key-value-value-value (string-string-integer-integer) 00340 * set to host. 00341 * 00342 * \param key Message key (message/event name) 00343 * \param value Message payload, string value 00344 * \param passes Send additional integer formatted data 00345 * \param failures Send additional integer formatted data 00346 * 00347 */ 00348 void greentea_send_kv(const char *key, const char *val, const int passes, const int failures) { 00349 if (key) { 00350 greentea_write_preamble(); 00351 greentea_write_string(key); 00352 greentea_serial->putc(';'); 00353 greentea_write_string(val); 00354 greentea_serial->putc(';'); 00355 greentea_write_int(passes); 00356 greentea_serial->putc(';'); 00357 greentea_write_int(failures); 00358 greentea_write_postamble(); 00359 } 00360 } 00361 00362 /** 00363 * \brief Encapsulate and send key-value-value message from DUT to host 00364 * 00365 * This function uses underlying functions to write directly 00366 * to the serial port, (USBTX). This allows key-value-value to be used 00367 * from within interrupt context. 00368 * Both values are integers to avoid integer to string conversion 00369 * made by the user. 00370 * 00371 * Names of the parameters: this function is used to send number 00372 * of passes and failures to host. But it can be used to send any 00373 * key-value-value (string-integer-integer) message to host. 00374 * 00375 * \param key Message key (message/event name) 00376 * \param value Message payload, integer value 00377 * \param passes Send additional integer formatted data 00378 * \param failures Send additional integer formatted data 00379 * 00380 */ 00381 void greentea_send_kv(const char *key, const int passes, const int failures) { 00382 if (key) { 00383 greentea_write_preamble(); 00384 greentea_write_string(key); 00385 greentea_serial->putc(';'); 00386 greentea_write_int(passes); 00387 greentea_serial->putc(';'); 00388 greentea_write_int(failures); 00389 greentea_write_postamble(); 00390 } 00391 } 00392 00393 /** 00394 * \brief Send message with timeout to master in seconds 00395 * 00396 * GREENTEA_TEST_ENV_TIMEOUT message is part of preamble 00397 * sent from DUT to host during synchronisation (beginning of test 00398 * suite execution). 00399 * 00400 * Notification about total test suite timeout. Timeout is measured 00401 * from the moment of GREENTEA_TEST_ENV_TIMEOUT reception by host. 00402 * If timeout is reached host (and host test) will be stopped and 00403 * control will return to Greentea. 00404 * 00405 * \param timeout Test suite timeout in seconds 00406 * 00407 */ 00408 static void greentea_notify_timeout(const int timeout) { 00409 greentea_send_kv(GREENTEA_TEST_ENV_TIMEOUT, timeout); 00410 } 00411 00412 /** 00413 * \brief Send host test name to master 00414 * 00415 * GREENTEA_TEST_ENV_HOST_TEST_NAME message is part of preamble 00416 * sent from DUT to host during synchronisation (beginning of test 00417 * suite execution). 00418 * 00419 * Host test Python script implements host side callbacks 00420 * for key-value events sent from DUT to host. Host test's 00421 * callbacks are registered after GREENTEA_TEST_ENV_HOST_TEST_NAME 00422 * message reaches host. 00423 * 00424 * \param host_test_name Host test name, host test will be loaded by mbedhtrun 00425 */ 00426 static void greentea_notify_hosttest(const char *host_test_name) { 00427 greentea_send_kv(GREENTEA_TEST_ENV_HOST_TEST_NAME, host_test_name); 00428 } 00429 00430 /** 00431 * \brief Send to master information that test suite finished its execution 00432 * 00433 * GREENTEA_TEST_ENV_END and GREENTEA_TEST_ENV_EXIT messages 00434 * are sent just before test suite execution finishes (noting 00435 * else to do). You can place it just before you return from your 00436 * main() function. 00437 * 00438 * Code coverage: If MEBD_CFG_DEBUG_OPTIONS_COVERAGE is set in the 00439 * project via build configuration function will output series 00440 * of code coverage messages GREENTEA_TEST_ENV_LCOV_START with code 00441 * coverage binary data. This data is captured by Greentea and can 00442 * be used to generate LCOV reports. 00443 * 00444 * \param result Test suite result from DUT (0 - FAIl, !0 - SUCCESS) 00445 * 00446 */ 00447 static void greentea_notify_completion(const int result) { 00448 const char *val = result ? GREENTEA_TEST_ENV_SUCCESS : GREENTEA_TEST_ENV_FAILURE; 00449 #ifdef MBED_CFG_DEBUG_OPTIONS_COVERAGE 00450 coverage_report = true; 00451 __gcov_flush(); 00452 coverage_report = false; 00453 #endif 00454 greentea_send_kv(GREENTEA_TEST_ENV_END, val); 00455 greentea_send_kv(GREENTEA_TEST_ENV_EXIT, 0); 00456 } 00457 00458 /** 00459 * \brief Send to master greentea-client version 00460 */ 00461 static void greentea_notify_version() { 00462 greentea_send_kv(GREENTEA_TEST_ENV_HOST_TEST_VERSION, MBED_GREENTEA_CLIENT_VERSION_STRING); 00463 } 00464 00465 /** 00466 ***************************************************************************** 00467 * Parse engine for KV values which replaces scanf 00468 ***************************************************************************** 00469 * 00470 * Example usage: 00471 * 00472 * char key[10]; 00473 * char value[48]; 00474 * 00475 * greentea_parse_kv(key, value, 10, 48); 00476 * greentea_parse_kv(key, value, 10, 48); 00477 * 00478 */ 00479 00480 00481 static int gettok(char *, const int); 00482 static int getNextToken(char *, const int); 00483 static int HandleKV(char *, char *, const int, const int); 00484 static int isstring(int); 00485 static int _get_char(); 00486 00487 /** 00488 * \brief Current token of key-value protocol's tokenizer 00489 */ 00490 static int CurTok = 0; 00491 00492 /** 00493 * \enum Token enumeration for key-value protocol tokenizer 00494 * 00495 * This enum is used by key-value protocol tokenizer 00496 * to detect parts of protocol in stream. 00497 * 00498 * tok_eof ::= EOF (end of file) 00499 * tok_open ::= "{{" 00500 * tok_close ::= "}}" 00501 * tok_semicolon ::= ";" 00502 * tok_string ::= [a-zA-Z0-9_-!@#$%^&*()]+ // See isstring() function 00503 * 00504 */ 00505 enum Token { 00506 tok_eof = -1, 00507 tok_open = -2, 00508 tok_close = -3, 00509 tok_semicolon = -4, 00510 tok_string = -5 00511 }; 00512 00513 /** 00514 * \brief Read character from stream of data 00515 * 00516 * Closure for default "get character" function. 00517 * This function is used to read characters from the stream 00518 * (default is serial port RX). Key-value protocol tokenizer 00519 * will build stream of tokes used by key-value protocol to 00520 * detect valid messages. 00521 * 00522 * If EOF is received parser finishes parsing and stops. In 00523 * situation where we have serial port stream of data parsing 00524 * goes forever. 00525 * 00526 * \return Next character from the stream or EOF if stream has ended. 00527 * 00528 */ 00529 static int _get_char() { 00530 return getchar(); 00531 } 00532 00533 /** 00534 * \brief parse input string for key-value pairs: {{key;value}} 00535 * This function should replace scanf() used to 00536 * check for incoming messages from master. All data 00537 * parsed and rejected is discarded. 00538 * 00539 * \param out_key Ouput data with key 00540 * \param out_value Ouput data with value 00541 * \param out_key_size out_key total size 00542 * \param out_value_size out_value total data 00543 * 00544 * success != 0 when key-value pair was found 00545 * success == 0 when end of the stream was found 00546 * 00547 */ 00548 int greentea_parse_kv(char *out_key, 00549 char *out_value, 00550 const int out_key_size, 00551 const int out_value_size) { 00552 getNextToken(0, 0); 00553 while (1) { 00554 switch (CurTok) { 00555 case tok_eof: 00556 return 0; 00557 00558 case tok_open: 00559 if (HandleKV(out_key, out_value, out_key_size, out_value_size)) { 00560 // We've found {{ KEY ; VALUE }} expression 00561 return 1; 00562 } 00563 break; 00564 00565 default: 00566 // Load next token and pray... 00567 getNextToken(0, 0); 00568 break; 00569 } 00570 } 00571 return 0; 00572 } 00573 00574 /** 00575 * \brief Get next token from stream 00576 * 00577 * Key-value TOKENIZER feature 00578 * 00579 * This function is used by key-value parser determine 00580 * if key-value message is embedded in stream data. 00581 * 00582 * \param str Output parameters to store token string value 00583 * \param str_size Size of 'str' parameter in bytes (characters) 00584 * 00585 */ 00586 static int getNextToken(char *str, const int str_size) { 00587 return CurTok = gettok(str, str_size); 00588 } 00589 00590 /** 00591 * \brief Check if character is punctuation character 00592 * 00593 * Auxilary key-value TOKENIZER function 00594 * 00595 * Defines if character is in subset of allowed punctuation 00596 * characters which can be part of a key or value string. 00597 * Not allowed characters are: ";{}" 00598 * 00599 * \param c Input character to check 00600 * \return Return 1 if character is allowed punctuation character, otherwise return false 00601 * 00602 */ 00603 static int ispunctuation(int c) { 00604 static const char punctuation[] = "_-!@#$%^&*()=+:<>,./?\\\"'"; // No ";{}" 00605 for (size_t i=0; i< sizeof(punctuation); ++i) { 00606 if (c == punctuation[i]) { 00607 return 1; 00608 } 00609 } 00610 return 0; 00611 } 00612 00613 /** 00614 * \brief Check if character is string token character 00615 * 00616 * Auxilary key-value TOKENIZER function 00617 * 00618 * Defines if character is in subset of allowed string 00619 * token characters. 00620 * String defines set of characters which can be a key or value string. 00621 * 00622 * Allowed subset includes: 00623 * - Alphanumerical characters 00624 * - Digits 00625 * - White spaces and 00626 * - subset of punctuation characters. 00627 * 00628 * \param c Input character to check 00629 * \return Return 1 if character is allowed punctuation character, otherwise return false 00630 * 00631 */ 00632 static int isstring(int c) { 00633 return (isalpha(c) || 00634 isdigit(c) || 00635 isspace(c) || 00636 ispunctuation(c)); 00637 } 00638 00639 /** 00640 * \brief TOKENIZER of key-value protocol 00641 * 00642 * Actual key-value TOKENIZER engine 00643 * 00644 * TOKENIZER defines #Token enum to map recognized tokens to integer values. 00645 * 00646 * <TOK_EOF> ::= EOF (end of file) 00647 * <TOK_OPEN> ::= "{{" 00648 * <TOK_CLOSE> ::= "}}" 00649 * <TOK_SEMICOLON> ::= ";" 00650 * <TOK_STRING> ::= [a-zA-Z0-9_-!@#$%^&*()]+ // See isstring() function * 00651 * 00652 * \param out_str Output string with parsed token (string) 00653 * \param str_size Size of str buffer we can use 00654 * 00655 * \return Return #Token enum value used by parser to check for key-value occurrences 00656 * 00657 */ 00658 static int gettok(char *out_str, const int str_size) { 00659 static int LastChar = '!'; 00660 static int str_idx = 0; 00661 00662 // whitespace ::= 00663 while (isspace(LastChar)) { 00664 LastChar = _get_char(); 00665 } 00666 00667 // string ::= [a-zA-Z0-9_-!@#$%^&*()]+ 00668 if (isstring(LastChar)) { 00669 str_idx = 0; 00670 if (out_str && str_idx < str_size - 1) { 00671 out_str[str_idx++] = LastChar; 00672 } 00673 00674 while (isstring((LastChar = _get_char()))) 00675 if (out_str && str_idx < str_size - 1) { 00676 out_str[str_idx++] = LastChar; 00677 } 00678 if (out_str && str_idx < str_size) { 00679 out_str[str_idx] = '\0'; 00680 } 00681 00682 return tok_string; 00683 } 00684 00685 // semicolon ::= ';' 00686 if (LastChar == ';') { 00687 LastChar = _get_char(); 00688 return tok_semicolon; 00689 } 00690 00691 // open ::= '{{' 00692 if (LastChar == '{') { 00693 LastChar = _get_char(); 00694 if (LastChar == '{') { 00695 LastChar = _get_char(); 00696 return tok_open; 00697 } 00698 } 00699 00700 // close ::= '}' 00701 if (LastChar == '}') { 00702 LastChar = _get_char(); 00703 if (LastChar == '}') { 00704 //LastChar = _get_char(); 00705 return tok_close; 00706 } 00707 } 00708 00709 if (LastChar == EOF) 00710 return tok_eof; 00711 00712 // Otherwise, just return the character as its ascii value. 00713 int ThisChar = LastChar; 00714 LastChar = _get_char(); 00715 return ThisChar; 00716 } 00717 00718 /** 00719 * \brief Key-value parser 00720 * 00721 * Key-value message grammar 00722 * 00723 * <MESSAGE>: <TOK_OPEN> <TOK_STRING> <TOK_SEMICOLON> <TOK_STRING> <TOK_CLOSE> 00724 * 00725 * Examples: 00726 * message: "{{__timeout; 1000}}" 00727 * "{{__sync; 12345678-1234-5678-1234-567812345678}}" 00728 * 00729 * \param out_key Output buffer to store key string value 00730 * \param out_value Output buffer to store value string value 00731 * \param out_key_size Buffer 'out_key' buffer size 00732 * \param out_value_size Buffer 'out_value_size' buffer size 00733 * \return Returns 1 if key-value message was parsed successfully in stream of tokens from tokenizer 00734 * 00735 */ 00736 static int HandleKV(char *out_key, 00737 char *out_value, 00738 const int out_key_size, 00739 const int out_value_size) { 00740 // We already started with <open> 00741 if (getNextToken(out_key, out_key_size) == tok_string) { 00742 if (getNextToken(0, 0) == tok_semicolon) { 00743 if (getNextToken(out_value, out_value_size) == tok_string) { 00744 if (getNextToken(0, 0) == tok_close) { 00745 // <open> <string> <semicolon> <string> <close> 00746 // Found "{{KEY;VALUE}}" expression 00747 return 1; 00748 } 00749 } 00750 } 00751 } 00752 getNextToken(0, 0); 00753 return 0; 00754 }
Generated on Tue Jul 12 2022 11:02:02 by
1.7.2
