aboutsummaryrefslogblamecommitdiffstats
path: root/util/string/util.h
blob: 0d77a5042b8fc0a89287f5268bc8917f5ba54ffd (plain) (tree)
1
2
3
4
5
6
7
8
9
            
 
                                
                  
                  
                    
 
                                 
                                
                                
 
                                     
                          
 
                                                   



                                       
 
                                                                           
                                                  


                                       
 

                                                                                                                                          
                                                                 
                                 
                               



                                      
 
      






                                                                     
                
                          
                         
                                             
  

                                                                  


                                                             
 

                                                                        
                                          
                

                 
                                                         
                

                 
                                                                               
                                           
                
                 
 
                                                          
                

                 
                                                                  

                                     
 


                                                    
                                                               

                                      
 


                                                     
                              
                                                      
     
 
                               
                                                       
     
                                               
                               



                                                      
                                               
               
                           
                              




                             
                        


                   
                                                  
                        

                               
          
                                         



                                     
                            
                       
                                 
     
                                               
                           
                                       
                 
                                      
                                              
                                     
     
                                


                  
                                                             
  
                                                         
                                                                      
                                                                                        
                                 
               

                                                                          
                       
#pragma once

//THIS FILE A COMPAT STUB HEADER

#include <cstring>
#include <cstdarg>
#include <algorithm>

#include <util/system/defaults.h>
#include <util/generic/string.h>
#include <util/generic/strbuf.h>

/// @addtogroup Strings_Miscellaneous
/// @{
int a2i(const TString& s);

/// Removes the last character if it is equal to c.
template <class T>
inline void RemoveIfLast(T& s, int c) {
    const size_t length = s.length();
    if (length && s[length - 1] == c)
        s.remove(length - 1);
}

/// Adds lastCh symbol to the the of the string if it is not already there.
inline void addIfNotLast(TString& s, int lastCh) {
    size_t len = s.length();
    if (!len || s[len - 1] != lastCh) {
        s.append(char(lastCh));
    }
}

/// @details Finishes the string with lastCh1 if lastCh2 is not present in the string and lastCh1 is not already at the end of the string.
/// Else, if lastCh2 is not equal to the symbol before the last, it finishes the string with lastCh2.
/// @todo ?? Define, when to apply the function. Is in use several times for URLs parsing.
inline void addIfAbsent(TString& s, char lastCh1, char lastCh2) {
    size_t pos = s.find(lastCh2);
    if (pos == TString::npos) {
        //s.append((char)lastCh1);
        addIfNotLast(s, lastCh1);
    } else if (pos < s.length() - 1) {
        addIfNotLast(s, lastCh2);
    }
}

/// @}

/*
 * ------------------------------------------------------------------
 *
 * A fast implementation of glibc's functions;
 *      strspn, strcspn and strpbrk.
 *
 * ------------------------------------------------------------------
 */
struct ui8_256 {
    // forward chars table
    ui8 chars_table[256];
    // reverse (for c* functions) chars table
    ui8 c_chars_table[256];
};

class str_spn: public ui8_256 {
public:
    explicit str_spn(const char* charset, bool extended = false) {
        // exteneded: if true, treat charset string more like
        // interior of brackets [ ], e.g. "a-z0-9"
        init(charset, extended);
    }

    /// Return first character in table, like strpbrk()
    /// That is, skip all characters not in table
    /// [DIFFERENCE FOR NOT_FOUND CASE: Returns end of string, not NULL]
    const char* brk(const char* s) const {
        while (c_chars_table[(ui8)*s])
            ++s;
        return s;
    }

    const char* brk(const char* s, const char* e) const {
        while (s < e && c_chars_table[(ui8)*s])
            ++s;
        return s;
    }

    /// Return first character not in table, like strpbrk() for inverted table.
    /// That is, skip all characters in table
    const char* cbrk(const char* s) const {
        while (chars_table[(ui8)*s])
            ++s;
        return s;
    }

    const char* cbrk(const char* s, const char* e) const {
        while (s < e && chars_table[(ui8)*s])
            ++s;
        return s;
    }

    /// Offset of the first character not in table, like strspn().
    size_t spn(const char* s) const {
        return cbrk(s) - s;
    }

    size_t spn(const char* s, const char* e) const {
        return cbrk(s, e) - s;
    }

    /// Offset of the first character in table, like strcspn().
    size_t cspn(const char* s) const {
        return brk(s) - s;
    }

    size_t cspn(const char* s, const char* e) const {
        return brk(s, e) - s;
    }

    char* brk(char* s) const {
        return const_cast<char*>(brk((const char*)s));
    }

    char* cbrk(char* s) const {
        return const_cast<char*>(cbrk((const char*)s));
    }

    /// See strsep [BUT argument is *&, not **]
    char* sep(char*& s) const {
        char sep_char; // unused;
        return sep(s, sep_char);
    }

    /// strsep + remember character that was destroyed
    char* sep(char*& s, char& sep_char) const {
        if (!s)
            return nullptr;
        char* ret = s;
        char* next = brk(ret);
        if (*next) {
            sep_char = *next;
            *next = 0;
            s = next + 1;
        } else {
            sep_char = 0;
            s = nullptr;
        }
        return ret;
    }

protected:
    void init(const char* charset, bool extended);
    str_spn() = default;
};

// an analogue of tr/$from/$to/
class Tr {
public:
    Tr(const char* from, const char* to);

    char ConvertChar(char ch) const {
        return Map[(ui8)ch];
    }

    void Do(char* s) const {
        for (; *s; s++)
            *s = ConvertChar(*s);
    }
    void Do(const char* src, char* dst) const {
        for (; *src; src++)
            *dst++ = ConvertChar(*src);
        *dst = 0;
    }
    void Do(char* s, size_t l) const {
        for (size_t i = 0; i < l && s[i]; i++)
            s[i] = ConvertChar(s[i]);
    }
    void Do(TString& str) const;

private:
    char Map[256];

    size_t FindFirstChangePosition(const TString& str) const;
};

// Removes all occurrences of given character from string
template <typename TStringType>
void RemoveAll(TStringType& str, typename TStringType::char_type ch) {
    size_t pos = str.find(ch); // 'find' to avoid cloning of string in 'TString.begin()'
    if (pos == TStringType::npos)
        return;

    typename TStringType::iterator begin = str.begin();
    typename TStringType::iterator end = begin + str.length();
    typename TStringType::iterator it = std::remove(begin + pos, end, ch);
    str.erase(it, end);
}