ERROR_CODE decode_bencoding_file(char *file_path, struct type_t **type_pointer) { /* allocates space for the general (temporary) variables to be used durring the parsing of the file */ ERROR_CODE return_value; size_t file_size; unsigned char *file_buffer; struct bencoding_engine_t *bencoding_engine; struct bencoding_handler_t *bencoding_handler; /* reads the file contained in the provided file path and then tests the error code for error, in case there is an error prints it to the error stream output */ return_value = read_file(file_path, &file_buffer, &file_size); if(IS_ERROR_CODE(return_value)) { RAISE_ERROR_F( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem reading file %s", file_path ); } /* starts the bencoding engine, starting all of its internal structures and then runs an engine tick parsing the complete file buffer (it's completely available) */ _start_bencoding_engine(&bencoding_engine); _run_bencoding_engine(bencoding_engine, file_buffer, file_size); /* retieves the handler associated with the engine and then uses it to retrieve the top type of the parsed structure */ bencoding_handler = (struct bencoding_handler_t *) bencoding_engine->context; *type_pointer = bencoding_handler->top; /* stops the bencoding engine releasing all of its internal structures, the top type is still defined */ _stop_bencoding_engine(bencoding_engine); /* releases the buffer used durring the parsing of the configuration file */ FREE(file_buffer); /* raises no error */ RAISE_NO_ERROR; }
ERROR_CODE process_ini_file(char *file_path, struct sort_map_t **configuration_pointer) { /* allocates space for the general (temporary) variables to be used durring the parsing of the file */ ERROR_CODE return_value; size_t index; size_t file_size; unsigned char *file_buffer; unsigned char character; enum ini_state_e state; /* allocates the mark variables used to locate the part of context changing durring the parsing */ unsigned char *pointer = 0; unsigned char *section_end_mark = 0; unsigned char *comment_end_mark = 0; unsigned char *key_end_mark = 0; unsigned char *value_end_mark = 0; /* allocates space for the settings to be used by the engine for the engine instance itself and for the handler to be used to "catch" the events, then retrieves the pointers to these structures*/ struct ini_settings_t ini_settings_s; struct ini_engine_t ini_engine_s; struct ini_handler_t ini_handler_s; struct ini_settings_t *ini_settings = &ini_settings_s; struct ini_engine_t *ini_engine = &ini_engine_s; struct ini_handler_t *ini_handler = &ini_handler_s; /* allocates space for the sort map to be used for the configuration to be created */ struct sort_map_t *configuration; /* creates the sort map that will hold the various arguments, then updates the configuration pointer with the created configuration sort map */ create_sort_map(&configuration, 0); *configuration_pointer = configuration; /* sets the various handlers for the ini settings parsing, they will be used to correctly update the provided configuration sort map */ ini_settings_s.on_section_start = NULL; ini_settings_s.on_section_end = _ini_section_end_callback; ini_settings_s.on_comment_start = NULL; ini_settings_s.on_comment_end = _ini_comment_end_callback; ini_settings_s.on_key_start = NULL; ini_settings_s.on_key_end = _ini_key_end_callback; ini_settings_s.on_value_start = NULL; ini_settings_s.on_value_end = _ini_value_end_callback; /* sets the configuration reference in the ini handler so that it may be updatd and then sets the handler in the ini engine instance to be used for parsing */ ini_handler_s.configuration = configuration; ini_engine_s.context = ini_handler; /* sets the flag that controls if the trailing space characters should be removesd from key and values */ ini_handler_s.remove_spaces = 1; /* reads the file contained in the provided file path and then tests the error code for error, in case there is an error prints it to the error stream output */ return_value = read_file(file_path, &file_buffer, &file_size); if(IS_ERROR_CODE(return_value)) { RAISE_ERROR_F( RUNTIME_EXCEPTION_ERROR_CODE, (unsigned char *) "Problem reading file %s", file_path ); } /* sets the initial state for the parsing process this is considered to be the "general loop" state */ state = INI_ENGINE_NORMAL; /* iterates over the byte range of the file, all the bytes should be contained in the buffer "under" iteration */ for(index = 0; index < file_size; index++) { /* retrieves the current character from the file buffer and the retrieves the pointer to its position */ character = file_buffer[index]; pointer = &file_buffer[index]; switch(state) { case INI_ENGINE_NORMAL: if(character == '[') { state = INI_ENGINE_SECTION; INI_MARK_N(section_end, -1); INI_CALLBACK(section_start); } else if(character == ';') { state = INI_ENGINE_COMMENT; INI_MARK_N(comment_end, -1); INI_CALLBACK(comment_start); } else if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; } else { state = INI_ENGINE_KEY; INI_MARK(key_end); INI_CALLBACK(key_start); } break; case INI_ENGINE_SECTION: if(character == ']') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(section_end); } break; case INI_ENGINE_COMMENT: if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(comment_end); } break; case INI_ENGINE_KEY: if(character == '=') { state = INI_ENGINE_VALUE; INI_MARK_N(value_end, -1); INI_CALLBACK_DATA(key_end); INI_CALLBACK(value_start); } break; case INI_ENGINE_VALUE: if(character == '\n' || character == '\r') { state = INI_ENGINE_NORMAL; INI_CALLBACK_DATA(value_end); } break; } } /* releases the buffer used durring the parsing of the configuration file (avoids leaks) */ FREE(file_buffer); /* raises no error */ RAISE_NO_ERROR; }