[glom] Correct the export to use the CSV format as per the RFC "specification".



commit af4b5026fa706a6509f0a3c52457ce3454bf57d2
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Jul 8 21:07:12 2009 +0200

    Correct the export to use the CSV format as per the RFC "specification".
    
    	* glom/frame_glom.cc: export_data_to_stream(): For text fields, add
    	" as per the CSV RFC.
    	* glom/libglom/data_structure/field.cc: to_file_format(): Escape
    	" as "". Note that we do not try to escape newlines. This is per the
    	CSV RFC.
    	* glom/libglom/utils.cc: string_replace(): In the loop, do not check
    	what has already been processed, to avoid an infinite loop.
    
    	Ubuntu bug https://bugs.launchpad.net/ubuntu/+source/glom/+bug/394894
    	(elmergato)

 ChangeLog                            |   15 +++++++++++++++
 glom/dialog_existing_or_new.cc       |    2 +-
 glom/dialog_import_csv_progress.cc   |    6 +++---
 glom/frame_glom.cc                   |   20 +++++++++++++++++---
 glom/libglom/data_structure/field.cc |    5 ++++-
 glom/libglom/utils.cc                |   13 ++++++++++---
 6 files changed, 50 insertions(+), 11 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 28ae014..efb0655 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-07-08  Murray Cumming  <murrayc murrayc com>
+
+	Correct the export to use the CSV format as per the RFC "specification".
+
+	* glom/frame_glom.cc: export_data_to_stream(): For text fields, add 
+	" as per the CSV RFC.
+	* glom/libglom/data_structure/field.cc: to_file_format(): Escape 
+	" as "". Note that we do not try to escape newlines. This is per the 
+	CSV RFC.
+	* glom/libglom/utils.cc: string_replace(): In the loop, do not check 
+	what has already been processed, to avoid an infinite loop.
+
+	Ubuntu bug https://bugs.launchpad.net/ubuntu/+source/glom/+bug/394894
+	(elmergato)
+
 2009-07-07  Murray Cumming  <murrayc murrayc com>
 
 	Catch libgda meta-store exceptions.
diff --git a/glom/dialog_existing_or_new.cc b/glom/dialog_existing_or_new.cc
index e0c8c94..bf771fc 100644
--- a/glom/dialog_existing_or_new.cc
+++ b/glom/dialog_existing_or_new.cc
@@ -18,7 +18,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <libglom/libglom_config.h>
+#include "config.h"
 #include "dialog_existing_or_new.h"
 
 #include <libxml++/parsers/saxparser.h>
diff --git a/glom/dialog_import_csv_progress.cc b/glom/dialog_import_csv_progress.cc
index ec73835..70936d1 100644
--- a/glom/dialog_import_csv_progress.cc
+++ b/glom/dialog_import_csv_progress.cc
@@ -144,11 +144,11 @@ bool Dialog_Import_CSV_Progress::on_idle_import()
     const sharedptr<Field>& field = m_data_source->get_field_for_column(i);
     if(field)
     {
-      // We always assume exported data is in postgres format, since
+      // We always assume exported data is in standard CSV format, since
       // we export it this way.
-      // TODO: Document what that format is.
+      const Glib::ustring str = m_data_source->get_data(m_current_row, i);
       bool success = false;
-      Gnome::Gda::Value value = field->from_file_format(m_data_source->get_data(m_current_row, i), success);
+      Gnome::Gda::Value value = field->from_file_format(str, success);
 
       if(success)
       {
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index 35d4113..f4ab4af 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -754,7 +754,22 @@ void Frame_Glom::export_data_to_stream(std::ostream& the_stream, const FoundSet&
               row_string += ",";
 
             //Output data in canonical SQL format, ignoring the user's locale, and ignoring the layout formatting:
-            row_string += layout_item->get_full_field_details()->to_file_format(value);
+            sharedptr<const Field> field = layout_item->get_full_field_details();
+            if(!field)
+            {
+              std::cerr << "Glom: Frame_Glom::export_data_to_stream(): A field was null." << std::endl;
+              return;
+            }
+
+            const Glib::ustring field_text = field->to_file_format(value);
+
+            if(layout_item->get_glom_type() == Field::TYPE_TEXT)
+            {
+              //The CSV RFC says text may be quoted and should be if it has newlines:
+              row_string += ("\"" + field_text + "\""); 
+            }
+            else
+              row_string += field_text;
 
             if(layout_item->get_glom_type() == Field::TYPE_IMAGE) //This is too much data.
             {
@@ -775,8 +790,7 @@ void Frame_Glom::on_menu_file_import()
 {
   if(m_table_name.empty())
   {
-    Gtk::MessageDialog dialog(*get_app_window(), "There is no table to import data into", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
-    dialog.run();
+    Utils::show_ok_dialog(_("No Table"), _("There is no table in to which data could be imported."), *get_app_window(), Gtk::MESSAGE_ERROR);
   }
   else
   {
diff --git a/glom/libglom/data_structure/field.cc b/glom/libglom/data_structure/field.cc
index 3f0cefc..41f50cd 100644
--- a/glom/libglom/data_structure/field.cc
+++ b/glom/libglom/data_structure/field.cc
@@ -289,7 +289,10 @@ Glib::ustring Field::to_file_format(const Gnome::Gda::Value& value, glom_field_t
   }
   
   NumericFormat format_ignored; //Because we use ISO format.
-  return Conversions::get_text_for_gda_value(glom_type, value, std::locale() /* SQL uses the C locale */, format_ignored, true /* ISO standard */);
+  const Glib::ustring result = Conversions::get_text_for_gda_value(glom_type, value, std::locale() /* SQL uses the C locale */, format_ignored, true /* ISO standard */);
+  
+  //Escape " as "", as specified by the CSV RFC:
+  return Utils::string_replace(result, "\"", "\"\"");
 }
 
 namespace
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index 32e4bc6..f4b1d4f 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -134,14 +134,21 @@ Glib::ustring Utils::trim_whitespace(const Glib::ustring& text)
 
 Glib::ustring Utils::string_replace(const Glib::ustring& src, const Glib::ustring search_for, const Glib::ustring& replace_with)
 {
+  //std::cout << "debug: Utils::string_replace(): src=" << src << ", search_for=" << search_for << ", replace_with=" << replace_with << std::endl;
+
   std::string result = src;
 
   std::string::size_type pos = 0;
-  std::string::size_type len= search_for.size();
+  std::string::size_type len_search = search_for.size();
+  std::string::size_type len_replace = replace_with.size();
 
-  while((pos = result.find(search_for)) != std::string::npos)
+  std::string::size_type pos_after_prev = 0;
+  while((pos = result.find(search_for, pos_after_prev)) != std::string::npos)
   {
-   result.replace(pos, len, replace_with);
+    //std::cout << "  debug: before: result =" << result << ", pos_after_prev=pos_after_prev" << std::endl;
+    result.replace(pos, len_search, replace_with);
+    //std::cout << "  after: before: result = result" << std::endl;
+    pos_after_prev = pos + len_replace;
   }
 
   return result;



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