blob: d5c16eb00316b8c544b8692d619549d2ef36b964 [file] [log] [blame]
/**
* @file unc_text.cpp
* A simple class that handles the chunk text.
*
* @author Ben Gardner
* @license GPL v2+
*/
#include "unc_text.h"
#include "prototypes.h" /* encode_utf8() */
static void fix_len_idx(int size, int& idx, int& len)
{
if (len < 0)
{
len = size;
}
if (len > 0)
{
if (idx < 0)
{
idx += size;
if (idx < 0)
{
idx = 0;
len = 0;
return;
}
}
if (idx >= size)
{
len = 0;
}
else
{
int left = size - idx;
if (len > left)
{
len = left;
}
}
}
}
void unc_text::update_logtext()
{
if (!m_logok)
{
/* make a pessimistic guess at the size */
m_logtext.clear();
m_logtext.reserve(m_chars.size() * 3);
for (value_type::iterator it = m_chars.begin(); it != m_chars.end(); ++it)
{
int val = *it;
if (*it == '\n')
{
val = 0x2424;
}
else if (*it == '\r')
{
val = 0x240d;
}
encode_utf8(val, m_logtext);
}
m_logtext.push_back(0);
m_logok = true;
}
}
int unc_text::compare(const unc_text& ref1, const unc_text& ref2, int len)
{
int idx, len1, len2;
len1 = ref1.size();
len2 = ref2.size();
if (len > 0)
{
for (idx = 0; (idx < len1) && (idx < len2) && (idx < len); idx++)
{
if (ref1.m_chars[idx] != ref2.m_chars[idx])
{
return(ref1.m_chars[idx] - ref2.m_chars[idx]);
}
}
if (idx == len)
{
return 0;
}
return(len1 - len2);
}
for (idx = 0; (idx < len1) && (idx < len2); idx++)
{
if (ref1.m_chars[idx] != ref2.m_chars[idx])
{
return(ref1.m_chars[idx] - ref2.m_chars[idx]);
}
}
return (len1 - len2);
}
bool unc_text::equals(const unc_text& ref) const
{
int len = size();
if (ref.size() != len)
{
return false;
}
for (int idx = 0; idx < len; idx++)
{
if (m_chars[idx] != ref.m_chars[idx])
{
return false;
}
}
return true;
}
const char *unc_text::c_str()
{
update_logtext();
return (const char *)&m_logtext[0];
}
void unc_text::set(int ch)
{
m_chars.clear();
m_chars.push_back(ch);
m_logok = false;
}
void unc_text::set(const unc_text& ref)
{
m_chars = ref.m_chars;
m_logok = false;
}
void unc_text::set(const unc_text& ref, int idx, int len)
{
int size = ref.size();
fix_len_idx(size, idx, len);
m_logok = false;
if ((idx == 0) && (len == size))
{
m_chars = ref.m_chars;
}
else
{
m_chars.resize(len);
int di = 0;
while (len-- > 0)
{
m_chars[di++] = ref.m_chars[idx++];
}
}
}
void unc_text::set(const string& ascii_text)
{
int len = ascii_text.size();
m_chars.resize(len);
for (int idx = 0; idx < len; idx++)
{
m_chars[idx] = ascii_text[idx];
}
m_logok = false;
}
void unc_text::set(const char *ascii_text)
{
int len = strlen(ascii_text);
m_chars.resize(len);
for (int idx = 0; idx < len; idx++)
{
m_chars[idx] = *ascii_text++;
}
m_logok = false;
}
void unc_text::set(const value_type& data, int idx, int len)
{
fix_len_idx(data.size(), idx, len);
m_chars.resize(len);
int di = 0;
while (len-- > 0)
{
m_chars[di++] = data[idx++];
}
m_logok = false;
}
void unc_text::resize(size_t new_size)
{
if (size() != (int)new_size)
{
m_chars.resize(new_size);
m_logok = false;
}
}
void unc_text::clear()
{
m_chars.clear();
m_logok = false;
}
void unc_text::insert(int idx, int ch)
{
if (idx >= 0)
{
m_chars.insert(m_chars.begin() + idx, ch);
m_logok = false;
}
}
void unc_text::insert(int idx, const unc_text& ref)
{
if (idx >= 0)
{
m_chars.insert(m_chars.begin() + idx, ref.m_chars.begin(), ref.m_chars.end());
m_logok = false;
}
}
void unc_text::append(int ch)
{
m_chars.push_back(ch);
m_logok = false;
}
void unc_text::append(const unc_text& ref)
{
m_chars.insert(m_chars.end(), ref.m_chars.begin(), ref.m_chars.end());
m_logok = false;
}
void unc_text::append(const string& ascii_text)
{
unc_text tmp(ascii_text);
append(tmp);
}
void unc_text::append(const char *ascii_text)
{
unc_text tmp(ascii_text);
append(tmp);
}
void unc_text::append(const value_type& data, int idx, int len)
{
unc_text tmp(data, idx, len);
append(tmp);
}
bool unc_text::startswith(const char *text, int idx) const
{
bool match = false;
while ((idx < size()) && *text)
{
if (*text != m_chars[idx])
{
return false;
}
idx++;
text++;
match = true;
}
return(match && (*text == 0));
}
bool unc_text::startswith(const unc_text& text, int idx) const
{
bool match = false;
int si = 0;
while ((idx < size()) && (si < text.size()))
{
if (text.m_chars[si] != m_chars[idx])
{
return false;
}
idx++;
si++;
match = true;
}
return(match && (si == text.size()));
}
int unc_text::find(const char *text, int sidx) const
{
int len = strlen(text);
int midx = size() - len;
int idx, ii;
for (idx = sidx; idx <= midx; idx++)
{
bool match = true;
for (ii = 0; ii < len; ii++)
{
if (m_chars[idx + ii] != text[ii])
{
match = false;
break;
}
}
if (match)
{
return idx;
}
}
return -1;
}
int unc_text::rfind(const char *text, int sidx) const
{
int len = strlen(text);
int midx = size() - len;
if ((sidx < 0) || (sidx > midx))
{
sidx = midx;
}
for (int idx = sidx; idx >= 0; idx--)
{
bool match = true;
for (int ii = 0; ii < len; ii++)
{
if (m_chars[idx + ii] != text[ii])
{
match = false;
break;
}
}
if (match)
{
return idx;
}
}
return -1;
}
void unc_text::erase(int idx, int len)
{
if (len >= 1)
{
m_chars.erase(m_chars.begin() + idx, m_chars.begin() + idx + len);
}
}
int unc_text::replace(const char *oldtext, const unc_text& newtext)
{
int fidx = find(oldtext);
int olen = strlen(oldtext);
int rcnt = 0;
while (fidx >= 0)
{
rcnt++;
erase(fidx, olen);
insert(fidx, newtext);
fidx = find(oldtext, fidx + newtext.size() - olen + 1);
}
return rcnt;
}