// get_properties.inl // Note: str_type, llil_int_type and map_str_int_type are not defined here. // llil_int_type is normally defined as: typedef int_fast64_t llil_int_type; // Note: int_fast64_t is defined in // map_str_int_type is keyed by str_type with value of llil_int_type. // These three types must be defined by the code that includes this .inl file. // map_str_int_type can be many different types, std::map, std::unordered_map, ... // so long as all operations on map_upd below are supported. #include #include #include #include inline llil_int_type fast_atoll64( const char* str ) { llil_int_type val = 0; // int sign = 0; // if ( *str == '-' ) { // sign = 1, ++str; // } uint8_t digit; while ((digit = uint8_t(*str++ - '0')) <= 9) val = val * 10 + digit; // return sign ? -val : val; return val; } // Limit line length and use ANSI C functions to try to boost performance #define MAX_LINE_LEN_L 255 // Update map_upd with the properties found in file fname // Return the number of properties in file fname (or -1 if fname could not be opened) static llil_int_type get_properties( const char* fname, // in : the input file name map_str_int_type& map_upd // inout: the map to be updated ) { std::array line; char* found; llil_int_type count; llil_int_type nprop = 0; FILE* fh = ::fopen(fname, "r"); if ( fh == NULL ) return -1; while ( ::fgets( line.data(), static_cast(MAX_LINE_LEN_L), fh ) != NULL ) { ++nprop; found = std::find( line.begin(), line.end(), '\t' ); count = fast_atoll64( found + 1 ); // Note: using emplace() is faster than map_upd[fixword] += count; #ifdef MAX_STR_LEN_L str_type fixword {}; // {} initializes all elements of fixword to '\0' std::copy( line.begin(), found, fixword.begin() ); const auto [it, success] = map_upd.emplace( fixword, count ); #else *found = '\0'; const auto [it, success] = map_upd.emplace(str_type{ line.data() }, count); #endif if (!success) it->second += count; } ::fclose(fh); return nprop; }