Esempio n. 1
0
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);
}
Esempio n. 2
0
bool unc_text::startswith(const unc_text &text, size_t idx) const
{
   size_t     si       = 0;
   const auto orig_idx = idx;

   for ( ; idx < size() && si < text.size(); idx++, si++)
   {
      if (text.m_chars[si] != m_chars[idx])
      {
         return(false);
      }
   }

   return(idx != orig_idx && (si == text.size()));
}
Esempio n. 3
0
static int next_up(const unc_text& text, int idx, unc_text& tag)
{
   int offs = 0;

   while ((idx < text.size()) && unc_isspace(text[idx]))
   {
      idx++;
      offs++;
   }

   if (text.startswith(tag, idx))
   {
      return(offs);
   }
   return(-1);
}
Esempio n. 4
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()));
}
Esempio n. 5
0
static void add_text(const unc_text& text)
{
   for (int idx = 0; idx < text.size(); idx++)
   {
      add_char(text[idx]);
   }
}
Esempio n. 6
0
int unc_text::compare(const unc_text &ref1, const unc_text &ref2, size_t len, bool tcare)
{
   const size_t len1    = ref1.size();
   const size_t len2    = ref2.size();
   const auto   max_idx = std::min({ len, len1, len2 });
   size_t       idx     = 0;

   for ( ; idx < max_idx; idx++)
   {
      // exactly the same character ?
      if (ref1.m_chars[idx] == ref2.m_chars[idx])
      {
         continue;
      }

      int diff;                                             // Issue #2091
      if (tcare)
      {
         diff = ref1.m_chars[idx] - ref2.m_chars[idx];
      }
      else
      {
         diff = unc_tolower(ref1.m_chars[idx]) - unc_tolower(ref2.m_chars[idx]);
      }
      if (diff == 0)
      {
         /*
          * if we're comparing the same character but in different case
          * we want to favor lower case before upper case (e.g. a before A)
          * so the order is the reverse of ASCII order (we negate).
          */
         return(-(ref1.m_chars[idx] - ref2.m_chars[idx]));
      }

      // return the case-insensitive diff to sort alphabetically
      return(diff);
   }

   if (idx == len)
   {
      return(0);
   }

   // underflow save: return(len1 - len2);
   return((len1 > len2) ? (len1 - len2) : -static_cast<int>(len2 - len1));
} // unc_text::compare
Esempio n. 7
0
/**
 * Checks for and updates the lead chars.
 *
 * @param line the comment line
 * @return 0=not present, >0=number of chars that are part of the lead
 */
static int cmt_parse_lead(const unc_text& line, int is_last)
{
   int len = 0;

   while ((len < 32) && (len < line.size()))
   {
      if ((len > 0) && (line[len] == '/'))
      {
         /* ignore combined comments */
         int tmp = len + 1;
         while ((tmp < line.size()) && unc_isspace(line[tmp]))
         {
            tmp++;
         }
         if ((tmp < line.size()) && (line[tmp] == '/'))
         {
            return 1;
         }
         break;
      }
      else if (strchr("*|\\#+", line[len]) == NULL)
      {
         break;
      }
      len++;
   }

   if (len > 30)
   {
      return 1;
   }

   if ((len > 0) && ((len >= line.size()) || unc_isspace(line[len])))
   {
      return len;
   }
   if ((len == 1) && (line[0] == '*'))
   {
      return len;
   }
   if (is_last && (len > 0))
   {
      return len;
   }
   return 0;
}
Esempio n. 8
0
/**
 * Count the number of characters to the end of the next chunk of text.
 * If it exceeds the limit, return true.
 */
static bool next_word_exceeds_limit(const unc_text& text, int idx)
{
   int length = 0;

   /* Count any whitespace */
   while ((idx < text.size()) && unc_isspace(text[idx]))
   {
      idx++;
      length++;
   }

   /* Count non-whitespace */
   while ((idx < text.size()) && !unc_isspace(text[idx]))
   {
      idx++;
      length++;
   }
   return((cpd.column + length - 1) > cpd.settings[UO_cmt_width].n);
}
Esempio n. 9
0
/**
 * This renders the #if condition to a string buffer.
 */
static void generate_if_conditional_as_text(unc_text& dst, chunk_t *ifdef)
{
   chunk_t *pc;
   int     column = -1;

   dst.clear();
   for (pc = ifdef; pc != NULL; pc = chunk_get_next(pc))
   {
      if (column == -1)
      {
         column = pc->column;
      }
      if ((pc->type == CT_NEWLINE) ||
          (pc->type == CT_COMMENT_MULTI) ||
          (pc->type == CT_COMMENT_CPP))
      {
         break;
      }
      else if (pc->type == CT_NL_CONT)
      {
         dst   += ' ';
         column = -1;
      }
      else if ((pc->type == CT_COMMENT) ||
               (pc->type == CT_COMMENT_EMBED))
      {
      }
      else // if (pc->type == CT_JUNK) || else
      {
         int spacing;

         for (spacing = pc->column - column; spacing > 0; spacing--)
         {
            dst += ' ';
            column++;
         }
         dst.append(pc->str);
         column += pc->len();
      }
   }
}
Esempio n. 10
0
void unc_text::append(const unc_text &ref)
{
   if (ref.size() == 0)
   {
      return;
   }

   m_logtext.pop_back();
   m_logtext.insert(std::end(m_logtext),
                    std::begin(ref.m_logtext), std::end(ref.m_logtext));

   m_chars.insert(m_chars.end(), ref.m_chars.begin(), ref.m_chars.end());
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
bool unc_text::equals(const unc_text &ref) const
{
   const size_t len = size();

   if (ref.size() != len)
   {
      return(false);
   }

   for (size_t idx = 0; idx < len; idx++)
   {
      if (m_chars[idx] != ref.m_chars[idx])
      {
         return(false);
      }
   }
   return(true);
}
Esempio n. 14
0
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++];
      }
   }
}
Esempio n. 15
0
int unc_text::replace(const char *search_text, const unc_text &replace_text)
{
   const size_t s_len = strlen(search_text);
   const size_t r_len = replace_text.size();

   int          rcnt = 0;
   int          fidx = find(search_text);

   while (fidx >= 0)
   {
      rcnt++;
      erase(static_cast<size_t>(fidx), s_len);

      (static_cast<size_t>(fidx) >= m_chars.size())
      ? append(replace_text)
      : insert(static_cast<size_t>(fidx), replace_text);

      fidx = find(search_text, static_cast<size_t>(fidx) + r_len);
   }
   return(rcnt);
}
Esempio n. 16
0
void unc_text::set(const unc_text &ref, size_t idx, size_t len)
{
   const auto ref_size = ref.size();

   if (len == ref_size)
   {
      m_chars = ref.m_chars;
      update_logtext();
      return;
   }

   m_chars.resize(len);

   len = fix_len_idx(ref_size, idx, len);
   for (size_t di = 0;
        len > 0;
        di++, idx++, len--)
   {
      m_chars[di] = ref.m_chars[idx];
   }


   update_logtext();
}
Esempio n. 17
0
void unc_text::insert(size_t idx, const unc_text &ref)
{
   if (ref.size() == 0)
   {
      return;
   }
   if (idx >= m_chars.size())
   {
      throw out_of_range(string(__func__) + ":" + to_string(__LINE__)
                         + " - idx >= m_chars.size()");
   }

   const auto utf8_idx = getLogTextUtf8Len(m_chars, idx);
   // (A+B) remove \0 from both containers, add back a single at the end
   m_logtext.pop_back(); // A
   m_logtext.insert(std::next(std::begin(m_logtext), utf8_idx),
                    std::begin(ref.m_logtext),
                    std::prev(std::end(ref.m_logtext))); // B
   m_logtext.push_back('\0');


   m_chars.insert(std::next(std::begin(m_chars), idx),
                  std::begin(ref.m_chars), std::end(ref.m_chars));
}
Esempio n. 18
0
/**
 * Scans a multiline comment to determine the following:
 *  - the extra indent of the non-first line (0 or 1)
 *  - the continuation text ('' or '* ')
 *
 * The decision is based on:
 *  - cmt_indent_multi
 *  - cmt_star_cont
 *  - the first line length
 *  - the second line leader length
 *  - the last line length
 *
 * If the first and last line are the same length and don't contain any alnum
 * chars and (the first line len > 2 or the second leader is the same as the
 * first line length), then the indent is 0.
 *
 * If the leader on the second line is 1 wide or missing, then the indent is 1.
 *
 * Otherwise, the indent is 0.
 *
 * @param str       The comment string
 * @param len       Length of the comment
 * @param start_col Starting column
 * @return 0 or 1
 */
static void calculate_comment_body_indent(cmt_reflow &cmt, const unc_text& str)
{
   int idx       = 0;
   int first_len = 0;
   int last_len  = 0;
   int width     = 0;
   int len       = str.size();

   cmt.xtra_indent = 0;

   if (!cpd.settings[UO_cmt_indent_multi].b)
   {
      return;
   }

   if (cpd.settings[UO_cmt_multi_check_last].b)
   {
      /* find the last line length */
      for (idx = len - 1; idx > 0; idx--)
      {
         if ((str[idx] == '\n') || (str[idx] == '\r'))
         {
            idx++;
            while ((idx < len) && ((str[idx] == ' ') || (str[idx] == '\t')))
            {
               idx++;
            }
            last_len = len - idx;
            break;
         }
      }
   }

   /* find the first line length */
   for (idx = 0; idx < len; idx++)
   {
      if ((str[idx] == '\n') || (str[idx] == '\r'))
      {
         first_len = idx;
         while ((str[first_len - 1] == ' ') || (str[first_len - 1] == '\t'))
         {
            first_len--;
         }

         /* handle DOS endings */
         if ((str[idx] == '\r') && (str[idx + 1] == '\n'))
         {
            idx++;
         }
         idx++;
         break;
      }
   }

   /* Scan the second line */
   width = 0;
   for (/* nada */; idx < len - 1; idx++)
   {
      if ((str[idx] == ' ') || (str[idx] == '\t'))
      {
         if (width > 0)
         {
            break;
         }
         continue;
      }
      if ((str[idx] == '\n') || (str[idx] == '\r'))
      {
         /* Done with second line */
         break;
      }

      /* Count the leading chars */
      if ((str[idx] == '*') ||
          (str[idx] == '|') ||
          (str[idx] == '\\') ||
          (str[idx] == '#') ||
          (str[idx] == '+'))
      {
         width++;
      }
      else
      {
         if ((width != 1) || (str[idx - 1] != '*'))
         {
            width = 0;
         }
         break;
      }
   }

   //LOG_FMT(LSYS, "%s: first=%d last=%d width=%d\n", __func__, first_len, last_len, width);

   /*TODO: make the first_len minimum (4) configurable? */
   if ((first_len == last_len) && ((first_len > 4) || (first_len == width)))
   {
      return;
   }

   cmt.xtra_indent = ((width == 2) ? 0 : 1);
}
Esempio n. 19
0
/**
 * text starts with '$('. see if this matches a keyword and add text based
 * on that keyword.
 * @return the number of characters eaten from the text
 */
static int add_comment_kw(const unc_text& text, int idx, cmt_reflow& cmt)
{
   if (text.startswith("$(filename)", idx))
   {
      add_text(path_basename(cpd.filename));
      return(11);
   }
   if (text.startswith("$(class)", idx))
   {
      chunk_t *tmp = get_next_class(cmt.pc);
      if (tmp != NULL)
      {
         add_text(tmp->str);
         return(8);
      }
   }

   /* If we can't find the function, we are done */
   chunk_t *fcn = get_next_function(cmt.pc);
   if (fcn == NULL)
   {
      return(0);
   }

   if (text.startswith("$(message)", idx))
   {
      add_text(fcn->str);
      chunk_t *tmp = chunk_get_next_ncnl(fcn);
      chunk_t *word = NULL;
      while (tmp)
      {
         if ((tmp->type == CT_BRACE_OPEN) || (tmp->type == CT_SEMICOLON))
         {
            break;
         }
         if (tmp->type == CT_OC_COLON)
         {
            if (word != NULL)
            {
               add_text(word->str);
               word = NULL;
            }
            add_text(":");
         }
         if (tmp->type == CT_WORD)
         {
            word = tmp;
         }
         tmp = chunk_get_next_ncnl(tmp);
      }
      return(10);
   }
   if (text.startswith("$(function)", idx))
   {
      if (fcn->parent_type == CT_OPERATOR)
      {
         add_text("operator ");
      }
      add_text(fcn->str);
      return(11);
   }
   if (text.startswith("$(javaparam)", idx))
   {
      add_comment_javaparam(fcn, cmt);
      return(12);
   }
   if (text.startswith("$(fclass)", idx))
   {
      chunk_t *tmp = chunk_get_prev_ncnl(fcn);
      if ((tmp != NULL) && (tmp->type == CT_OPERATOR))
      {
         tmp = chunk_get_prev_ncnl(tmp);
      }
      if ((tmp != NULL) && ((tmp->type == CT_DC_MEMBER) ||
                            (tmp->type == CT_MEMBER)))
      {
         tmp = chunk_get_prev_ncnl(tmp);
         add_text(tmp->str);
         return(9);
      }
   }
   return(0);
}
Esempio n. 20
0
/**
 * Outputs a comment. The initial opening '//' may be included in the text.
 * Subsequent openings (if combining comments), should not be included.
 * The closing (for C/D comments) should not be included.
 *
 * TODO:
 * If reflowing text, the comment should be added one word (or line) at a time.
 * A newline should only be sent if a blank line is encountered or if the next
 * line is indented beyond the current line (optional?).
 * If the last char on a line is a ':' or '.', then the next line won't be
 * combined.
 */
static void add_comment_text(const unc_text& text,
                             cmt_reflow& cmt, bool esc_close)
{
   bool was_star   = false;
   bool was_slash  = false;
   bool was_dollar = false;
   bool in_word    = false;
   int  tmp;
   int  len = text.size();

   for (int idx = 0; idx < len; idx++)
   {
      if (!was_dollar && cmt.kw_subst &&
          (text[idx] == '$') && (len > (idx + 3)) && (text[idx + 1] == '('))
      {
         idx += add_comment_kw(text, idx, cmt);
         if (idx >= len)
         {
            break;
         }
      }

      /* Split the comment */
      if (text[idx] == '\n')
      {
         in_word = false;
         add_char('\n');
         cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
         if (cmt.xtra_indent)
         {
            add_char(' ');
         }

         /* hack to get escaped newlines to align and not dup the leading '//' */
         tmp = next_up(text, idx + 1, cmt.cont_text);
         if (tmp < 0)
         {
            add_text(cmt.cont_text);
         }
         else
         {
            idx += tmp;
         }
      }
      else if (cmt.reflow &&
               (text[idx] == ' ') &&
               (cpd.settings[UO_cmt_width].n > 0) &&
               ((cpd.column > cpd.settings[UO_cmt_width].n) ||
                next_word_exceeds_limit(text, idx)))
      {
         in_word = false;
         add_char('\n');
         cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
         if (cmt.xtra_indent)
         {
            add_char(' ');
         }
         add_text(cmt.cont_text);
      }
      else
      {
         /* Escape a C closure in a CPP comment */
         if (esc_close &&
             ((was_star && (text[idx] == '/')) ||
              (was_slash && (text[idx] == '*'))))
         {
            add_char(' ');
         }
         if (!in_word && !unc_isspace(text[idx]))
         {
            cmt.word_count++;
         }
         in_word = !unc_isspace(text[idx]);

         add_char(text[idx]);
         was_star   = (text[idx] == '*');
         was_slash  = (text[idx] == '/');
         was_dollar = (text[idx] == '$');
      }
   }
}
Esempio n. 21
0
static void cmt_trim_whitespace(unc_text& line, bool in_preproc)
{
   /* Remove trailing whitespace on the line */
   while ((line.size() > 0) &&
          ((line.back() == ' ') ||
           (line.back() == '\t')))
   {
      line.pop_back();
   }

   /* If in a preproc, shift any bs-nl back to the comment text */
   if (in_preproc && (line.size() > 1) && (line.back() == '\\'))
   {
      bool do_space = false;

      /* If there was any space before the backslash, change it to 1 space */
      line.pop_back();
      while ((line.size() > 0) &&
             ((line.back() == ' ') ||
              (line.back() == '\t')))
      {
         do_space = true;
         line.pop_back();
      }
      if (do_space)
      {
         line.append(' ');
      }
      line.append('\\');
   }
}