// Internal version of rf_string_find, used for byte position. int rf_string_find_byte_pos(const struct RFstring *tstr, const struct RFstring *sstr, const char options) { #define CHECK_NOT_CHAR(s_, i_) \ do{ \ /* if is is not a character */ \ switch(rf_string_data(s_)[i_]) \ { \ case ' ':case '\t':case '\n': \ break; \ default: \ return RF_FAILURE; \ break; \ } \ }while(0) const char* found = 0; RF_ASSERT(tstr, "got null string in function"); if (!sstr) { RF_WARNING("Provided null search string parameter"); return RF_FAILURE; } //search matching characters if(!RF_BITFLAG_ON(options, RF_CASE_IGNORE)) { //if it is not found if(!(found = strstr_nnt(rf_string_data(tstr), rf_string_length_bytes(tstr), rf_string_data(sstr), rf_string_length_bytes(sstr)))) return RF_FAILURE; //get the byte position uint32_t bytepos = found - rf_string_data(tstr); //if we need the exact string as it is given if(RF_BITFLAG_ON(options, RF_MATCH_WORD)) { //check before the found string if(bytepos != 0) { CHECK_NOT_CHAR(tstr, bytepos - 1); } //check after the found string if(bytepos + rf_string_length_bytes(sstr) != rf_string_length_bytes(tstr)) { //if is is not a character CHECK_NOT_CHAR(tstr, bytepos + rf_string_length_bytes(sstr)); } }//end of the exact string option //else return the position in the bytes buffer return bytepos; } //else, case insensitive search uint32_t i,j; for(i=0; i < rf_string_length_bytes(tstr); i ++) { //if i matches the start of the substring for(j = 0; j < rf_string_length_bytes(sstr); j++) { //if the jth char is a big letter if(rf_string_data(sstr)[j] >= 0x41 && rf_string_data(sstr)[j] <= 0x5a) { //no match if(rf_string_data(sstr)[j] != rf_string_data(tstr)[i+j] && rf_string_data(sstr)[j]+32 != rf_string_data(tstr)[i+j]) break; //there is a match in the jth character if(RF_BITFLAG_ON(options, RF_MATCH_WORD)) { /* if it's the first substring character and if the string we search is not in it's beginning, check for EXACT string before */ if(j == 0 && i != 0) { CHECK_NOT_CHAR(tstr, i - 1); } }//exact string check if ends } //small letter else if(rf_string_data(sstr)[j] >= 0x61 && rf_string_data(sstr)[j] <= 0x7a) { //no match if(rf_string_data(sstr)[j] != rf_string_data(tstr)[i+j] && rf_string_data(sstr)[j]-32 != rf_string_data(tstr)[i+j]) break; //there is a match in the jth character if(RF_BITFLAG_ON(options, RF_MATCH_WORD)) { /* if it's the first substring character and if the string we search is not in it's beginning, check for EXACT string before */ if(j == 0 && i != 0) { CHECK_NOT_CHAR(tstr, i - 1); } }//exact string check if ends } //not a letter and no match else if(rf_string_data(sstr)[j] != rf_string_data(tstr)[i+j]) { break;//break off the substring search loop } //we either found it or need to perform one last check for exact string if(j == rf_string_length_bytes(sstr) - 1) { //only if the end of the string is not right after the substring if(RF_BITFLAG_ON(options, RF_MATCH_WORD) && i + rf_string_length_bytes(sstr) < rf_string_length_bytes(tstr)) { CHECK_NOT_CHAR(tstr, i + rf_string_length_bytes(sstr)); }//end of the exact string check //succes return i; }//end of it's the last char of the substring check }//substring iteration ends }//this string iteration ends return RF_FAILURE; //getting here means nothing was found #undef CHECK_NOT_CHAR }
// Internal version of rfString_Find, used for byte position. int32_t rfString_FindBytePos(const void* str,const void* sstrP,char options) { RF_String* thisstr = (RF_String*)str; RF_String* sstr = (RF_String*)sstrP; char* found = 0; //if we want to match the case of the string then it's a simple search of matching characters if( (RF_BITFLAG_ON(options,RF_CASE_IGNORE)) == false) { //if it is not found if( (found = strstr(thisstr->bytes,sstr->bytes)) == 0) return RF_FAILURE; //get the byte position uint32_t bytepos = found-thisstr->bytes; //if we need the exact string as it is given if(RF_BITFLAG_ON(options,RF_MATCH_WORD)) { //check before the found string if(bytepos != 0) { //if is is not a character switch(thisstr->bytes[bytepos-1]) { case ' ':case '\t':case '\n': break; default: return RF_FAILURE; break; } } //check after the found string if(bytepos+sstr->byteLength != thisstr->byteLength) { //if is is not a character switch(thisstr->bytes[bytepos+sstr->byteLength]) { case ' ':case '\t':case '\n': break; default: return RF_FAILURE; break; } } }//end of the exact string option //else return the position in the bytes buffer return bytepos; } //else, case insensitive search uint32_t i,j; //if(cstr[0] >= 0x41 && cstr[0] <= 0x5a) for(i=0;i<thisstr->byteLength; i ++) { //if i matches the start of the substring for(j = 0; j < sstr->byteLength; j++) { //if the jth char is a big letter if(sstr->bytes[j] >= 0x41 && sstr->bytes[j] <= 0x5a) { //no match if(sstr->bytes[j] != thisstr->bytes[i+j] && sstr->bytes[j]+32 != thisstr->bytes[i+j]) break; //there is a match in the jth character so let's perform additional checks if needed if(RF_BITFLAG_ON(options,RF_MATCH_WORD)) { //if it's the first substring character and if the string we search is not in it's beginning, check for EXACT string before if(j == 0 && i != 0) { switch(thisstr->bytes[i-1]) { case ' ':case '\t':case '\n': break; default: return RF_FAILURE; break; } } }//exact string check if ends } //small letter else if(sstr->bytes[j] >= 0x61 && sstr->bytes[j] <= 0x7a) { //no match if(sstr->bytes[j] != thisstr->bytes[i+j] && sstr->bytes[j]-32 != thisstr->bytes[i+j]) break; //there is a match in the jth character so let's perform additional checks if needed if(RF_BITFLAG_ON(options,RF_MATCH_WORD)) { //if it's the first substring character and if the string we search is not in it's beginning, check for EXACT string before if(j == 0 && i != 0) { switch(thisstr->bytes[i-1]) { case ' ':case '\t':case '\n': break; default: return RF_FAILURE; break; } } }//exact string check if ends } //not a letter and no match else if(sstr->bytes[j] != thisstr->bytes[i+j]) break;//break off the substring search loop //if we get here and it's the last char of the substring we either found it or need to perform one last check for exact string if(j == sstr->byteLength-1) { //only if the end of the string is not right after the substring if( RF_BITFLAG_ON(options,RF_MATCH_WORD) && i+sstr->byteLength < thisstr->byteLength) { switch(thisstr->bytes[i+sstr->byteLength]) { case ' ':case '\t':case '\n': break; default: return RF_FAILURE; break; } }//end of the exact string check //succes return i; }//end of it's the last char of the substring check }//substring iteration ends }//this string iteration ends return RF_FAILURE; //getting here means nothing was found }