[glom] Move some functions to string_utils.h



commit 1d39c4561054e6fe407c0d71ab8c3569928997e5
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Mar 16 20:29:52 2016 +0100

    Move some functions to string_utils.h

 CMakeLists.txt                                     |    2 +
 glom/appwindow.cc                                  |    1 +
 glom/box_reports.cc                                |    1 +
 glom/frame_glom.cc                                 |    1 +
 glom/glom_import_po_all.cc                         |    1 +
 glom/libglom/data_structure/field.cc               |    1 +
 glom/libglom/data_structure/glomconversions.cc     |    2 +-
 glom/libglom/db_utils.cc                           |    1 +
 glom/libglom/document/document.cc                  |    1 +
 glom/libglom/filelist.am                           |    2 +
 glom/libglom/glom_postgres.cc                      |    1 +
 glom/libglom/string_utils.cc                       |  393 ++++++++++++++++++++
 glom/libglom/string_utils.h                        |   69 ++++
 glom/libglom/utils.cc                              |  356 +------------------
 glom/libglom/utils.h                               |   31 --
 glom/libglom/xml_utils.cc                          |    1 +
 glom/mode_data/db_adddel/db_adddel.cc              |    1 +
 glom/mode_design/box_db_table_relationships.cc     |    1 +
 glom/mode_design/dialog_add_related_table.cc       |    1 +
 glom/mode_design/fields/box_db_table_definition.cc |    1 +
 glom/mode_design/layout/dialog_layout_details.cc   |    1 +
 .../mode_design/print_layouts/box_print_layouts.cc |    1 +
 glom/utility_widgets/adddel/adddel.cc              |    1 +
 23 files changed, 484 insertions(+), 387 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 879136e..18b2d33 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -252,6 +252,8 @@ set(SOURCE_FILES
         glom/libglom/standard_table_prefs_fields.h
         glom/libglom/translations_po.cc
         glom/libglom/translations_po.h
+        glom/libglom/string_utils.cc
+        glom/libglom/string_utils.h
         glom/libglom/utils.cc
         glom/libglom/utils.h
         glom/libglom/xml_utils.cc
diff --git a/glom/appwindow.cc b/glom/appwindow.cc
index 1977c1b..f631da4 100644
--- a/glom/appwindow.cc
+++ b/glom/appwindow.cc
@@ -23,6 +23,7 @@
 #include <glom/appwindow.h>
 #include <glom/dialog_existing_or_new.h>
 #include <glom/bakery/dialog_offersave.h>
+#include <libglom/string_utils.h>
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 #include <glom/mode_design/translation/dialog_change_language.h>
diff --git a/glom/box_reports.cc b/glom/box_reports.cc
index 516ed80..5e1cee4 100644
--- a/glom/box_reports.cc
+++ b/glom/box_reports.cc
@@ -22,6 +22,7 @@
 #include <glom/appwindow.h>
 #include <libglom/algorithms_utils.h>
 #include <libglom/utils.h> //For bold_message()).
+#include <libglom/string_utils.h>
 #include <gtkmm/alignment.h>
 #include <gtkmm/dialog.h>
 #include <gtkmm/messagedialog.h>
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 502eb06..1077b91 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -27,6 +27,7 @@
 #include <glom/import_csv/dialog_import_csv_progress.h>
 #include <libglom/appstate.h>
 #include <libglom/db_utils_export.h>
+#include <libglom/string_utils.h>
 
 #include <libglom/connectionpool.h>
 
diff --git a/glom/glom_import_po_all.cc b/glom/glom_import_po_all.cc
index 89086a6..5c642e9 100644
--- a/glom/glom_import_po_all.cc
+++ b/glom/glom_import_po_all.cc
@@ -26,6 +26,7 @@
 #include <libglom/init.h>
 #include <libglom/translations_po.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <giomm/file.h>
 #include <glibmm/optioncontext.h>
 #include <glibmm/convert.h>
diff --git a/glom/libglom/data_structure/field.cc b/glom/libglom/data_structure/field.cc
index 575a32b..9d95ff4 100644
--- a/glom/libglom/data_structure/field.cc
+++ b/glom/libglom/data_structure/field.cc
@@ -23,6 +23,7 @@
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <libgda/gda-blob-op.h>
 #include <glibmm/i18n.h>
 
diff --git a/glom/libglom/data_structure/glomconversions.cc b/glom/libglom/data_structure/glomconversions.cc
index e1bf806..977085e 100644
--- a/glom/libglom/data_structure/glomconversions.cc
+++ b/glom/libglom/data_structure/glomconversions.cc
@@ -24,6 +24,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/connectionpool.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 
 #include <glibmm/convert.h>
 #include <sstream> //For stringstream
@@ -33,7 +34,6 @@
 #include <iostream>   // for cout, endl
 #include <iomanip>
 #include <string.h> // for strlen, memset, strcmp
-#include <stdexcept>
 
 #include <glibmm/i18n.h>
 
diff --git a/glom/libglom/db_utils.cc b/glom/libglom/db_utils.cc
index 48c780a..ff18b82 100644
--- a/glom/libglom/db_utils.cc
+++ b/glom/libglom/db_utils.cc
@@ -30,6 +30,7 @@
 #include <libgdamm/metastore.h>
 #include <glibmm/timer.h>
 #include <libgda/libgda.h> // For gda_g_type_from_string
+#include "string_utils.h"
 #include <glibmm/i18n.h>
 
 
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index bcd2b21..4fa7dee 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -22,6 +22,7 @@
 #include <libglom/xml_utils.h>
 #include <libglom/algorithms_utils.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 //#include <libglom/data_structure/glomconversions.h>
 #include <libglom/data_structure/layout/report_parts/layoutitem_summary.h>
 #include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
diff --git a/glom/libglom/filelist.am b/glom/libglom/filelist.am
index 8035f29..fecc488 100644
--- a/glom/libglom/filelist.am
+++ b/glom/libglom/filelist.am
@@ -117,6 +117,8 @@ libglom_sources =                                                   \
        glom/libglom/report_builder.h                                   \
        glom/libglom/spawn_with_feedback.cc                             \
        glom/libglom/spawn_with_feedback.h                              \
+       glom/libglom/string_utils.cc \
+       glom/libglom/string_utils.h \
        glom/libglom/translations_po.cc                         \
        glom/libglom/translations_po.h                          \
        glom/libglom/utils.cc                                           \
diff --git a/glom/libglom/glom_postgres.cc b/glom/libglom/glom_postgres.cc
index 4223a09..9584907 100644
--- a/glom/libglom/glom_postgres.cc
+++ b/glom/libglom/glom_postgres.cc
@@ -20,6 +20,7 @@
 
 #include "glom_postgres.h"
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 
 namespace Glom
 {
diff --git a/glom/libglom/string_utils.cc b/glom/libglom/string_utils.cc
new file mode 100644
index 0000000..31ae130
--- /dev/null
+++ b/glom/libglom/string_utils.cc
@@ -0,0 +1,393 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include "string_utils.h"
+#include <libglom/data_structure/field.h>
+#include <libglom/document/document.h>
+#include <giomm/file.h>
+#include <libglom/utils.h>
+#include <giomm/resource.h>
+#include <glibmm/convert.h>
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+#include <stack>
+#include <iostream>
+
+namespace Glom
+{
+
+namespace Utils
+{
+
+Glib::ustring trim_whitespace(const Glib::ustring& text)
+{
+  //TODO_Performance:
+
+  Glib::ustring result = text;
+
+  //Find non-whitespace from front:
+  Glib::ustring::size_type posFront = Glib::ustring::npos;
+  Glib::ustring::size_type pos = 0;
+  for (const auto& item : result)
+  {
+    if (!Glib::Unicode::isspace(item))
+    {
+      posFront = pos;
+      break;
+    }
+
+    ++pos;
+  }
+
+  //Remove the white space from the front:
+  result = result.substr(posFront);
+
+
+  //Find non-whitespace from back:
+  Glib::ustring::size_type posBack = Glib::ustring::npos;
+  pos = 0;
+  for (auto iter = result.rbegin(); iter != result.rend(); ++iter)
+  {
+    if (!Glib::Unicode::isspace(*iter))
+    {
+      posBack = pos;
+      break;
+    }
+
+    ++pos;
+  }
+
+  //Remove the white space from the front:
+  result = result.substr(0, result.size() - posBack);
+
+  return result;
+}
+
+Glib::ustring string_replace(const Glib::ustring& src, const Glib::ustring& search_for, const Glib::ustring& 
replace_with)
+{
+  if(search_for.empty())
+  {
+    std::cerr << G_STRFUNC << ": search_for was empty.\n";
+    return src;
+  }
+
+  //std::cout << "debug: " << G_STRFUNC << ": src=" << src << ", search_for=" << search_for << ", 
replace_with=" << replace_with << std::endl;
+
+  std::string result = src;
+
+  std::string::size_type pos = 0;
+  const std::string::size_type len_search = search_for.size();
+  const std::string::size_type len_replace = replace_with.size();
+
+  std::string::size_type pos_after_prev = 0;
+  while((pos = result.find(search_for, pos_after_prev)) != std::string::npos)
+  {
+    //std::cout << "  debug: pos=" << pos << ", found=" << search_for << ", in string: " << 
result.substr(pos_after_prev, 20) << std::endl;
+    //std::cout << "  debug: before: result =" << result << ", pos_after_prev=pos_after_prev\n";
+    result.replace(pos, len_search, replace_with);
+    //std::cout << "  after: before: result = result\n";
+    pos_after_prev = pos + len_replace;
+  }
+
+  return result;
+
+/*
+  //TODO_Performance:
+
+  Glib::ustring result;
+  const size_t src_length = src.size();
+  const size_t search_for_length = search_for.size();
+  //const size_t replace_with_length = replace_with.size();
+
+  size_t src_index = 0;
+  size_t src_index_section_start = 0;
+  while(src_index < src_length)
+  {
+    const bool found = (src.find(search_for, src_index) == src_index);
+    if(found)
+    {
+      result += src.substr(src_index_section_start, src_index - src_index_section_start);
+      result += replace_with;
+
+      src_index_section_start = src_index + search_for_length;
+      src_index = src_index_section_start;
+    }
+    else
+      ++src_index;
+  }
+
+  if(src_index_section_start < src_length)
+  {
+    result += src.substr(src_index_section_start);
+  }
+
+  return result;
+*/
+}
+
+Glib::ustring string_clean_for_xml(const Glib::ustring& src)
+{
+  // The form feed character may not be in XML, even if escaped.
+  // So lets just lose it.
+  // Other unusual characters, such as &, are escaped by libxml later.
+  // TODO_Performance: Find a quicker way to do this.
+  return string_replace(src, "\f", Glib::ustring());
+}
+
+Glib::ustring create_name_from_title(const Glib::ustring& title)
+{
+  Glib::ustring result = string_replace(title, " ", "");
+  return result.lowercase(); //TODO: Maybe they need to be ASCII (not UTF8)?
+}
+
+Glib::ustring string_escape_underscores(const Glib::ustring& text)
+{
+  Glib::ustring result;
+  for(const auto& item : text)
+  {
+    if(item == '_')
+      result += "__";
+    else
+      result += item;
+  }
+
+  return result;
+}
+
+Glib::ustring string_trim(const Glib::ustring& str, const Glib::ustring& to_remove)
+{
+  Glib::ustring result = str;
+
+  //Remove from the start:
+  Glib::ustring::size_type posOpenBracket = result.find(to_remove);
+  if(posOpenBracket == 0)
+  {
+    result = result.substr(to_remove.size());
+  }
+
+  //Remove from the end:
+  Glib::ustring::size_type posCloseBracket = result.rfind(to_remove);
+  if(posCloseBracket == (result.size() - to_remove.size()))
+  {
+    result = result.substr(0, posCloseBracket);
+  }
+
+  return result;
+}
+
+Glib::ustring string_remove_suffix(const Glib::ustring& str, const Glib::ustring& suffix, bool 
case_sensitive)
+{
+  //There is also g_string_has_suffix(), but I assume that is case sensitive. murrayc.
+
+  const Glib::ustring::size_type size = str.size();
+  const Glib::ustring::size_type suffix_size = suffix.size();
+  if(size < suffix_size)
+    return str;
+
+  const Glib::ustring possible_suffix = str.substr(size - suffix_size);
+
+  if(case_sensitive)
+  {
+    if(possible_suffix == suffix)
+      return str.substr(0, size - suffix_size);
+  }
+  else
+  {
+    if(g_ascii_strcasecmp(possible_suffix.c_str(), suffix.c_str()) == 0) //TODO: I don't understand the 
warnings about using this function in the glib documentation. murrayc.
+      return str.substr(0, size - suffix_size);
+  }
+
+  return str;
+}
+
+Glib::ustring title_from_string(const Glib::ustring& text)
+{
+  Glib::ustring result;
+
+  bool capitalise_next_char = true;
+  for(const auto& ch : text)
+  {
+    if(ch == '_') //Replace _ with space.
+    {
+      capitalise_next_char = true; //Capitalise all words.
+      result += " ";
+    }
+    else
+    {
+      if(capitalise_next_char)
+        result += Glib::Unicode::toupper(ch);
+      else
+        result += ch;
+
+      capitalise_next_char = false;
+    }
+  }
+
+  return result;
+}
+
+Glib::ustring string_from_decimal(guint decimal)
+{
+  //TODO_Performance:
+
+  std::stringstream stream;
+  stream.imbue(std::locale("")); //Use the user's current locale.
+  stream << decimal;
+
+  Glib::ustring result;
+  stream >> result;
+
+  return result;
+}
+
+type_vec_strings string_separate(const Glib::ustring& str, const Glib::ustring& separator, bool 
ignore_quoted_separator)
+{
+  //std::cout << "debug: " << G_STRFUNC << ": separator=" << separator << std::endl;
+
+  type_vec_strings result;
+
+  const Glib::ustring::size_type size = str.size();
+  const Glib::ustring::size_type size_separator = separator.size();
+
+  //A stack of quotes, so that we can handle nested quotes, whether they are " or ':
+  typedef std::stack<Glib::ustring> type_queue_quotes;
+  type_queue_quotes m_current_quotes;
+
+  Glib::ustring::size_type unprocessed_start = 0;
+  Glib::ustring::size_type item_start = 0;
+  while(unprocessed_start < size)
+  {
+    //std::cout << "while unprocessed: un_processed_start=" << unprocessed_start << std::endl;
+    Glib::ustring::size_type posComma = str.find(separator, unprocessed_start);
+
+    Glib::ustring item;
+    if(posComma != Glib::ustring::npos)
+    {
+      //Check that the separator was not in quotes:
+      bool in_quotes = false;
+
+      if(ignore_quoted_separator)
+      {
+        //std::cout << "  debug: attempting to ignore quoted separators: " << separator << std::endl;
+
+        Glib::ustring::size_type posLastQuote = unprocessed_start;
+
+        //std::cout << "    debug: posLastQuote=" << posLastQuote << std::endl;
+        //std::cout << "    debug: posComma=" << posComma << std::endl;
+
+
+        bool bContinue = true;
+        while(bContinue && (posLastQuote < posComma))
+        {
+          //std::cout << "  continue\n";
+          Glib::ustring closing_quote;
+          if(!m_current_quotes.empty())
+            closing_quote = m_current_quotes.top();
+
+          //std::cout << "   posLastQuote=" << posLastQuote << std::endl;
+          const Glib::ustring::size_type posSingleQuote = str.find("'", posLastQuote);
+          const Glib::ustring::size_type posDoubleQuote = str.find("\"", posLastQuote);
+
+          // std::cout << "   posSingleQuote=" << posSingleQuote << "posDoubleQuote=" << posDoubleQuote << 
std::endl;
+
+          //Which quote, if any, is first:
+          Glib::ustring::size_type posFirstQuote = posSingleQuote;
+          if( (posDoubleQuote != Glib::ustring::npos) && (posDoubleQuote < posFirstQuote) )
+            posFirstQuote = posDoubleQuote;
+
+          //Ignore quotes that are _after_ the separator:
+          if( posFirstQuote >= posComma)
+            posFirstQuote = Glib::ustring::npos;
+
+          //std::cout << "   posFirstQuote=" << posFirstQuote << std::endl;
+
+          //If any quote character was found:
+          if(posFirstQuote != Glib::ustring::npos)
+          {
+            //std::cout << "quote found: posFirstQuote=" << posFirstQuote << std::endl;
+
+            //Which quote was it?
+            const Glib::ustring first_quote =  (posFirstQuote == posSingleQuote ? "'" : "\"");
+            //std::cout << "   first_quote=" << first_quote << std::endl;
+
+            //Was it an expected closing quote, if we expected any:
+            if(first_quote == closing_quote)
+            {
+              //std::cout << "   popping quote\n";
+              //Yes, so remove that quote from our stack, because we found the closing quote:
+              m_current_quotes.pop();
+            }
+            else
+            {
+              //std::cout << "   pushing quote\n";
+              //This must be an opening quote, so remember it:
+              m_current_quotes.push(first_quote);
+            }
+
+            posLastQuote = posFirstQuote + 1; //Do the next find after the quote.
+          }
+          else
+          {
+            //There were no quotes, or no closing quotes:
+            bContinue = false;
+          }
+        } //while(bContinue)
+
+        //If there were any unclosed quotes then this separator must have been in quotes:
+        if(!m_current_quotes.empty())
+          in_quotes = true;
+      } //If ignore_quoted_separator
+
+      if(!in_quotes) //or if we don't care about quotes.
+      {
+        //std::cout << "!in_quotes\n";
+
+        //Store this item, and start the next item after it:
+        item = str.substr(item_start, posComma - item_start);
+        //std::cout << "  ITEM. pos_comma=" << posComma << ", ITEM= " << item << std::endl;
+        item_start = posComma + size_separator;
+      }
+      else
+      {
+        //std::cout << "in quotes.\n";
+        // Continue behind separator
+        unprocessed_start = posComma + size_separator;
+        // Do not add this item to the result, because it was quoted.
+        continue;
+      }
+
+      unprocessed_start = posComma + size_separator; //The while loops stops when this is empty.
+    }
+    else //if no separator found:
+    {
+      item = str.substr(item_start);
+      unprocessed_start = size; //Stop.
+    }
+
+    item = string_trim(item, " ");
+    result.emplace_back(item);
+  } //while
+
+  return result;
+}
+
+} //namespace Utils
+
+} //namespace Glom
\ No newline at end of file
diff --git a/glom/libglom/string_utils.h b/glom/libglom/string_utils.h
new file mode 100644
index 0000000..28c27ad
--- /dev/null
+++ b/glom/libglom/string_utils.h
@@ -0,0 +1,69 @@
+//
+// Created by murrayc on 3/16/16.
+//
+/* Glom
+ *
+ * Copyright (C) 2001-20016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <glibmm/ustring.h>
+#include <vector>
+
+#ifndef GLOM_STRING_UTILS_H
+#define GLOM_STRING_UTILS_H
+
+namespace Glom {
+
+namespace Utils {
+
+Glib::ustring trim_whitespace(const Glib::ustring &text);
+
+Glib::ustring string_replace(const Glib::ustring& src, const Glib::ustring& search_for, const Glib::ustring& 
replace_with);
+
+/** Remove any characters that may not be in XML even when escaped.
+ */
+Glib::ustring string_clean_for_xml(const Glib::ustring& src);
+
+/** Guess an appropriate identifier name based on a human-readable title
+ */
+Glib::ustring create_name_from_title(const Glib::ustring& title);
+
+Glib::ustring string_escape_underscores(const Glib::ustring& text);
+
+Glib::ustring string_trim(const Glib::ustring& str, const Glib::ustring& to_remove);
+
+Glib::ustring string_remove_suffix(const Glib::ustring& str, const Glib::ustring& suffix, bool 
case_sensitive = true);
+
+/** Create an appropriate title for an ID string.
+ * For instance, date_of_birth would become Date Of Birth.
+ */
+Glib::ustring title_from_string(const Glib::ustring& text);
+
+/** Get a decimal text representation of the number,
+ * in the current locale.
+ */
+Glib::ustring string_from_decimal(guint decimal);
+
+typedef std::vector<Glib::ustring> type_vec_strings;
+type_vec_strings string_separate(const Glib::ustring& str, const Glib::ustring& separator, bool 
ignore_quoted_separator = false);
+
+} //namespace Utils
+
+} //namespace Glom
+
+#endif //GLOM_STRING_UTILS_H
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index 69a4760..4446ba6 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -26,6 +26,7 @@
 #include <libglom/connectionpool.h>
 #include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
 #include <libglom/data_structure/glomconversions.h>
+#include <libglom/string_utils.h>
 
 #include <giomm/file.h>
 #include <giomm/resource.h>
@@ -74,122 +75,6 @@ auto find_if_uses_relationship_has_relationship(T_Container& container, const st
   );
 }
 
-Glib::ustring Utils::trim_whitespace(const Glib::ustring& text)
-{
-  //TODO_Performance:
-
-  Glib::ustring result = text;
-
-  //Find non-whitespace from front:
-  Glib::ustring::size_type posFront = Glib::ustring::npos;
-  Glib::ustring::size_type pos = 0;
-  for(const auto& item : result)
-  {
-    if(!Glib::Unicode::isspace(item))
-    {
-      posFront = pos;
-      break;
-    }
-
-    ++pos;
-  }
-
-  //Remove the white space from the front:
-  result = result.substr(posFront);
-
-
- //Find non-whitespace from back:
-  Glib::ustring::size_type posBack = Glib::ustring::npos;
-  pos = 0;
-  for(auto iter = result.rbegin(); iter != result.rend(); ++iter)
-  {
-    if(!Glib::Unicode::isspace(*iter))
-    {
-      posBack = pos;
-      break;
-    }
-
-    ++pos;
-  }
-
-  //Remove the white space from the front:
-  result = result.substr(0, result.size() - posBack);
-
-  return result;
-}
-
-Glib::ustring Utils::string_replace(const Glib::ustring& src, const Glib::ustring& search_for, const 
Glib::ustring& replace_with)
-{
-  if(search_for.empty())
-  {
-    std::cerr << G_STRFUNC << ": search_for was empty.\n";
-    return src;
-  }
-
-  //std::cout << "debug: " << G_STRFUNC << ": src=" << src << ", search_for=" << search_for << ", 
replace_with=" << replace_with << std::endl;
-
-  std::string result = src;
-
-  std::string::size_type pos = 0;
-  const std::string::size_type len_search = search_for.size();
-  const std::string::size_type len_replace = replace_with.size();
-
-  std::string::size_type pos_after_prev = 0;
-  while((pos = result.find(search_for, pos_after_prev)) != std::string::npos)
-  {
-    //std::cout << "  debug: pos=" << pos << ", found=" << search_for << ", in string: " << 
result.substr(pos_after_prev, 20) << std::endl;
-    //std::cout << "  debug: before: result =" << result << ", pos_after_prev=pos_after_prev\n";
-    result.replace(pos, len_search, replace_with);
-    //std::cout << "  after: before: result = result\n";
-    pos_after_prev = pos + len_replace;
-  }
-
-  return result;
-
-/*
-  //TODO_Performance:
-
-  Glib::ustring result;
-  const size_t src_length = src.size();
-  const size_t search_for_length = search_for.size();
-  //const size_t replace_with_length = replace_with.size();
-
-  size_t src_index = 0;
-  size_t src_index_section_start = 0;
-  while(src_index < src_length)
-  {
-    const bool found = (src.find(search_for, src_index) == src_index);
-    if(found)
-    {
-      result += src.substr(src_index_section_start, src_index - src_index_section_start);
-      result += replace_with;
-
-      src_index_section_start = src_index + search_for_length;
-      src_index = src_index_section_start;
-    }
-    else
-      ++src_index;
-  }
-
-  if(src_index_section_start < src_length)
-  {
-    result += src.substr(src_index_section_start);
-  }
-
-  return result;
-*/
-}
-
-Glib::ustring Utils::string_clean_for_xml(const Glib::ustring& src)
-{
-  // The form feed character may not be in XML, even if escaped.
-  // So lets just lose it.
-  // Other unusual characters, such as &, are escaped by libxml later.
-  // TODO_Performance: Find a quicker way to do this.
-  return string_replace(src, "\f", Glib::ustring());
-}
-
-
 Glib::RefPtr<Gnome::Gda::SqlBuilder> Utils::build_sql_select_with_where_clause(const Glib::ustring& 
table_name, const type_vecLayoutFields& fieldsToGet, const Gnome::Gda::SqlExpr& where_clause, const 
std::shared_ptr<const Relationship>& extra_join, const type_sort_clause& sort_clause, guint limit)
 {
   //TODO_Performance:
@@ -627,26 +512,6 @@ Utils::type_list_values_with_second Utils::get_choice_values(const std::shared_p
   return result;
 }
 
-Glib::ustring Utils::create_name_from_title(const Glib::ustring& title)
-{
-  Glib::ustring result = string_replace(title, " ", "");
-  return result.lowercase(); //TODO: Maybe they need to be ASCII (not UTF8)?
-}
-
-Glib::ustring Utils::string_escape_underscores(const Glib::ustring& text)
-{
-  Glib::ustring result;
-  for(const auto& item : text)
-  {
-    if(item == '_')
-      result += "__";
-    else
-      result += item;
-  }
-
-  return result;
-}
-
 /** Get just the first part of a locale, such as de_DE,
  * ignoring, for instance, .UTF-8 or \ euro at the end.
  */
@@ -750,225 +615,6 @@ Glib::ustring Utils::create_local_image_uri(const Gnome::Gda::Value& value)
   return ("file://" + result);
 }
 
-Glib::ustring Utils::string_from_decimal(guint decimal)
-{
-  //TODO_Performance:
-
-  std::stringstream stream;
-  stream.imbue(std::locale("")); //Use the user's current locale.
-  stream << decimal;
-
-  Glib::ustring result;
-  stream >> result;
-
-  return result;
-}
-
-Glib::ustring Utils::title_from_string(const Glib::ustring& text)
-{
-  Glib::ustring result;
-
-  bool capitalise_next_char = true;
-  for(const auto& ch : text)
-  {
-    if(ch == '_') //Replace _ with space.
-    {
-      capitalise_next_char = true; //Capitalise all words.
-      result += " ";
-    }
-    else
-    {
-      if(capitalise_next_char)
-        result += Glib::Unicode::toupper(ch);
-      else
-        result += ch;
-
-      capitalise_next_char = false;
-    }
-  }
-
-  return result;
-}
-
-Utils::type_vec_strings Utils::string_separate(const Glib::ustring& str, const Glib::ustring& separator, 
bool ignore_quoted_separator)
-{
-  //std::cout << "debug: " << G_STRFUNC << ": separator=" << separator << std::endl;
-
-  type_vec_strings result;
-
-  const Glib::ustring::size_type size = str.size();
-  const Glib::ustring::size_type size_separator = separator.size();
-
-  //A stack of quotes, so that we can handle nested quotes, whether they are " or ':
-  typedef std::stack<Glib::ustring> type_queue_quotes;
-  type_queue_quotes m_current_quotes;
-
-  Glib::ustring::size_type unprocessed_start = 0;
-  Glib::ustring::size_type item_start = 0;
-  while(unprocessed_start < size)
-  {
-    //std::cout << "while unprocessed: un_processed_start=" << unprocessed_start << std::endl;
-    Glib::ustring::size_type posComma = str.find(separator, unprocessed_start);
-
-    Glib::ustring item;
-    if(posComma != Glib::ustring::npos)
-    {
-      //Check that the separator was not in quotes:
-      bool in_quotes = false;
-
-      if(ignore_quoted_separator)
-      {
-        //std::cout << "  debug: attempting to ignore quoted separators: " << separator << std::endl;
-
-        Glib::ustring::size_type posLastQuote = unprocessed_start;
-
-        //std::cout << "    debug: posLastQuote=" << posLastQuote << std::endl;
-        //std::cout << "    debug: posComma=" << posComma << std::endl;
-
-
-        bool bContinue = true;
-        while(bContinue && (posLastQuote < posComma))
-        {
-          //std::cout << "  continue\n";
-          Glib::ustring closing_quote;
-          if(!m_current_quotes.empty())
-            closing_quote = m_current_quotes.top();
-
-          //std::cout << "   posLastQuote=" << posLastQuote << std::endl;
-          const Glib::ustring::size_type posSingleQuote = str.find("'", posLastQuote);
-          const Glib::ustring::size_type posDoubleQuote = str.find("\"", posLastQuote);
-
-         // std::cout << "   posSingleQuote=" << posSingleQuote << "posDoubleQuote=" << posDoubleQuote << 
std::endl;
-
-          //Which quote, if any, is first:
-          Glib::ustring::size_type posFirstQuote = posSingleQuote;
-          if( (posDoubleQuote != Glib::ustring::npos) && (posDoubleQuote < posFirstQuote) )
-            posFirstQuote = posDoubleQuote;
-
-          //Ignore quotes that are _after_ the separator:
-          if( posFirstQuote >= posComma)
-            posFirstQuote = Glib::ustring::npos;
-
-          //std::cout << "   posFirstQuote=" << posFirstQuote << std::endl;
-
-          //If any quote character was found:
-          if(posFirstQuote != Glib::ustring::npos)
-          {
-            //std::cout << "quote found: posFirstQuote=" << posFirstQuote << std::endl;
-
-            //Which quote was it?
-            const Glib::ustring first_quote =  (posFirstQuote == posSingleQuote ? "'" : "\"");
-            //std::cout << "   first_quote=" << first_quote << std::endl;
-
-            //Was it an expected closing quote, if we expected any:
-            if(first_quote == closing_quote)
-            {
-              //std::cout << "   popping quote\n";
-              //Yes, so remove that quote from our stack, because we found the closing quote:
-              m_current_quotes.pop();
-            }
-            else
-            {
-              //std::cout << "   pushing quote\n";
-              //This must be an opening quote, so remember it:
-              m_current_quotes.push(first_quote);
-            }
-
-            posLastQuote = posFirstQuote + 1; //Do the next find after the quote.
-          }
-          else
-          {
-            //There were no quotes, or no closing quotes:
-            bContinue = false;
-          }
-        } //while(bContinue)
-
-        //If there were any unclosed quotes then this separator must have been in quotes:
-        if(!m_current_quotes.empty())
-          in_quotes = true;
-      } //If ignore_quoted_separator
-
-      if(!in_quotes) //or if we don't care about quotes.
-      {
-        //std::cout << "!in_quotes\n";
-
-        //Store this item, and start the next item after it:
-        item = str.substr(item_start, posComma - item_start);
-        //std::cout << "  ITEM. pos_comma=" << posComma << ", ITEM= " << item << std::endl;
-        item_start = posComma + size_separator;
-      }
-      else
-      {
-        //std::cout << "in quotes.\n";
-        // Continue behind separator
-        unprocessed_start = posComma + size_separator;
-        // Do not add this item to the result, because it was quoted.
-        continue;
-      }
-
-      unprocessed_start = posComma + size_separator; //The while loops stops when this is empty.
-    }
-    else //if no separator found:
-    {
-        item = str.substr(item_start);
-        unprocessed_start = size; //Stop.
-    }
-
-    item = string_trim(item, " ");
-    result.emplace_back(item);
-  } //while
-
-  return result;
-}
-
-Glib::ustring Utils::string_trim(const Glib::ustring& str, const Glib::ustring& to_remove)
-{
-   Glib::ustring result = str;
-
-   //Remove from the start:
-   Glib::ustring::size_type posOpenBracket = result.find(to_remove);
-   if(posOpenBracket == 0)
-   {
-      result = result.substr(to_remove.size());
-   }
-
-   //Remove from the end:
-   Glib::ustring::size_type posCloseBracket = result.rfind(to_remove);
-   if(posCloseBracket == (result.size() - to_remove.size()))
-   {
-    result = result.substr(0, posCloseBracket);
-   }
-
-  return result;
-}
-
-Glib::ustring Utils::string_remove_suffix(const Glib::ustring& str, const Glib::ustring& suffix, bool 
case_sensitive)
-{
-  //There is also g_string_has_suffix(), but I assume that is case sensitive. murrayc.
-
-  const Glib::ustring::size_type size = str.size();
-  const Glib::ustring::size_type suffix_size = suffix.size();
-  if(size < suffix_size)
-    return str;
-
-  const Glib::ustring possible_suffix = str.substr(size - suffix_size);
-
-  if(case_sensitive)
-  {
-    if(possible_suffix == suffix)
-      return str.substr(0, size - suffix_size);
-  }
-  else
-  {
-    if(g_ascii_strcasecmp(possible_suffix.c_str(), suffix.c_str()) == 0) //TODO: I don't understand the 
warnings about using this function in the glib documentation. murrayc.
-      return str.substr(0, size - suffix_size);
-  }
-
-  return str;
-}
-
-
-
 bool Utils::file_exists(const Glib::ustring& uri)
 {
   if(uri.empty())
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index fe35caa..8e97020 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -40,14 +40,6 @@ typedef std::vector<type_pair_sort_field> type_sort_clause;
 namespace Utils
 {
 
-Glib::ustring trim_whitespace(const Glib::ustring& text);
-
-Glib::ustring string_replace(const Glib::ustring& src, const Glib::ustring& search_for, const Glib::ustring& 
replace_with);
-
-/** Remove any characters that may not be in XML even when escaped.
- */
-Glib::ustring string_clean_for_xml(const Glib::ustring& src);
-
 //typedef Base_DB::type_vecLayoutFields type_vecLayoutFields;
 typedef std::vector< std::shared_ptr<LayoutItem_Field> > type_vecLayoutFields;
 typedef std::vector< std::shared_ptr<const LayoutItem_Field> > type_vecConstLayoutFields;
@@ -144,12 +136,6 @@ type_list_values_with_second get_choice_values(const std::shared_ptr<const Docum
 std::string sqlbuilder_get_full_query(
   const Glib::RefPtr<const Gnome::Gda::SqlBuilder>& builder);
 
-/** Guess an appropriate identifier name based on a human-readable title
- */
-Glib::ustring create_name_from_title(const Glib::ustring& title);
-
-Glib::ustring string_escape_underscores(const Glib::ustring& text);
-
 /** Get just the first part of a locale, such as de_DE,
  * ignoring, for instance, .UTF-8 or \ euro at the end.
  */
@@ -161,23 +147,6 @@ Glib::ustring locale_language_id(const Glib::ustring& locale_id);
 
 Glib::ustring create_local_image_uri(const Gnome::Gda::Value& value);
 
-/** Get a decimal text representation of the number,
- * in the current locale.
- */
-Glib::ustring string_from_decimal(guint decimal);
-
-/** Create an appropriate title for an ID string.
- * For instance, date_of_birth would become Date Of Birth.
- */
-Glib::ustring title_from_string(const Glib::ustring& text);
-
-typedef std::vector<Glib::ustring> type_vec_strings;
-type_vec_strings string_separate(const Glib::ustring& str, const Glib::ustring& separator, bool 
ignore_quoted_separator = false);
-
-Glib::ustring string_trim(const Glib::ustring& str, const Glib::ustring& to_remove);
-
-Glib::ustring string_remove_suffix(const Glib::ustring& str, const Glib::ustring& suffix, bool 
case_sensitive = true);
-
 bool file_exists(const Glib::ustring& uri);
 bool file_exists(const Glib::RefPtr<Gio::File>& file);
 
diff --git a/glom/libglom/xml_utils.cc b/glom/libglom/xml_utils.cc
index f5ddab6..ff04619 100644
--- a/glom/libglom/xml_utils.cc
+++ b/glom/libglom/xml_utils.cc
@@ -20,6 +20,7 @@
 
 #include <libglom/xml_utils.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <limits> // for numeric_limits
 
 static const char GLOM_ATTRIBUTE_IMAGE_DATA_FORMAT[] = "format";
diff --git a/glom/mode_data/db_adddel/db_adddel.cc b/glom/mode_data/db_adddel/db_adddel.cc
index 9bbd113..40163c8 100644
--- a/glom/mode_data/db_adddel/db_adddel.cc
+++ b/glom/mode_data/db_adddel/db_adddel.cc
@@ -27,6 +27,7 @@
 #include "db_treeviewcolumn_glom.h"
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <glom/dialog_invalid_data.h>
 #include <glom/appwindow.h>
 #include <glom/utils_ui.h> //For UiUtils::image_scale_keeping_ratio().
diff --git a/glom/mode_design/box_db_table_relationships.cc b/glom/mode_design/box_db_table_relationships.cc
index 7340aa7..900d1cd 100644
--- a/glom/mode_design/box_db_table_relationships.cc
+++ b/glom/mode_design/box_db_table_relationships.cc
@@ -23,6 +23,7 @@
 #include <glom/appwindow.h>
 #include <libglom/db_utils.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <algorithm>
 #include <glibmm/i18n.h>
 
diff --git a/glom/mode_design/dialog_add_related_table.cc b/glom/mode_design/dialog_add_related_table.cc
index 6455145..2462240 100644
--- a/glom/mode_design/dialog_add_related_table.cc
+++ b/glom/mode_design/dialog_add_related_table.cc
@@ -22,6 +22,7 @@
 #include <glom/frame_glom.h> //For show_ok_dialog.h
 #include <libglom/db_utils.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
diff --git a/glom/mode_design/fields/box_db_table_definition.cc 
b/glom/mode_design/fields/box_db_table_definition.cc
index 8eb62df..2c36519 100644
--- a/glom/mode_design/fields/box_db_table_definition.cc
+++ b/glom/mode_design/fields/box_db_table_definition.cc
@@ -26,6 +26,7 @@
 #include <libglom/libglom_config.h>
 #include <libglom/db_utils.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
diff --git a/glom/mode_design/layout/dialog_layout_details.cc 
b/glom/mode_design/layout/dialog_layout_details.cc
index db6c035..6ee034b 100644
--- a/glom/mode_design/layout/dialog_layout_details.cc
+++ b/glom/mode_design/layout/dialog_layout_details.cc
@@ -26,6 +26,7 @@
 //#include <libgnome/gnome-i18n.h>
 #include <glom/utils_ui.h> //For bold_message()).
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <glom/appwindow.h>
 #include <glibmm/i18n.h>
 #include <sstream> //For stringstream
diff --git a/glom/mode_design/print_layouts/box_print_layouts.cc 
b/glom/mode_design/print_layouts/box_print_layouts.cc
index 9476d21..92b1814 100644
--- a/glom/mode_design/print_layouts/box_print_layouts.cc
+++ b/glom/mode_design/print_layouts/box_print_layouts.cc
@@ -24,6 +24,7 @@
 #include <gtkmm/messagedialog.h>
 #include <libglom/algorithms_utils.h>
 #include <libglom/utils.h> //For bold_message()).
+#include <libglom/string_utils.h>
 #include <glibmm/i18n.h>
 
 #include <iostream>
diff --git a/glom/utility_widgets/adddel/adddel.cc b/glom/utility_widgets/adddel/adddel.cc
index 30f5cf1..6e1df60 100644
--- a/glom/utility_widgets/adddel/adddel.cc
+++ b/glom/utility_widgets/adddel/adddel.cc
@@ -29,6 +29,7 @@
 #include <glom/dialog_invalid_data.h>
 #include <glom/utils_ui.h>
 #include <libglom/utils.h>
+#include <libglom/string_utils.h>
 #include <gtkmm/builder.h>
 #include <giomm/menu.h>
 //#include <glom/bakery/app_gtk.h>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]