[Aptitude-svn-commit] r3420 - in branches/aptitude-0.3/aptitude: . src/vscreen

Daniel Burrows dburrows@costa.debian.org
Sat, 25 Jun 2005 15:45:45 +0000


Author: dburrows
Date: Sat Jun 25 15:45:42 2005
New Revision: 3420

Added:
   branches/aptitude-0.3/aptitude/src/vscreen/transcode.cc
   branches/aptitude-0.3/aptitude/src/vscreen/transcode.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/vscreen/Makefile.am
Log:
Add an iconv wrapper to decode multibyte strings.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sat Jun 25 15:45:42 2005
@@ -1,5 +1,10 @@
 2005-06-25  Daniel Burrows  <dburrows@debian.org>
 
+	* src/vscreen/Makefile.am, src/vscreen/transcode.cc, src/vscreen/transcode.h:
+
+	  Add support code to wrap iconv in a simpler (less efficient)
+	  interface.
+
 	* src/vscreen/curses++.h:
 
 	  Fix formatting errors in a comment.

Modified: branches/aptitude-0.3/aptitude/src/vscreen/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/Makefile.am	Sat Jun 25 15:45:42 2005
@@ -82,7 +82,9 @@
 	vs_tree.h	\
 	vs_tree.cc	\
 	columnify.h	\
-	columnify.cc
+	columnify.cc	\
+	transcode.h	\
+	transcode.cc
 
 testvscreen_SOURCES=	\
 	testvscreen.cc

Added: branches/aptitude-0.3/aptitude/src/vscreen/transcode.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/vscreen/transcode.cc	Sat Jun 25 15:45:42 2005
@@ -0,0 +1,106 @@
+// transcode.cc
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#include "transcode.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <iconv.h>
+
+using namespace std;
+
+bool decode_multibyte(const char *s,
+		      wstring &out,
+		      const char *encoding)
+{
+  if(encoding == NULL)
+    encoding=setlocale(LC_CTYPE, NULL);
+
+  iconv_t converter=iconv_open("WCHAR_T", encoding);
+
+  if(converter==((iconv_t)-1))
+    return false;
+
+  // arbitrary initial starting size; expected to be large enough for
+  // most "small" strings.
+  size_t outbufsize=1024, outbufremaining=1024;
+  size_t inremaining=strlen(s);
+
+  try
+    {
+      // auto_ptr used so we free stuff automatically when we return
+      // (especially abnormally).
+      auto_ptr<char> outbufhead(new char[outbufsize]);
+      char *outbufcur=outbufhead.get();
+
+      while(inremaining>0)
+	{
+	  if(iconv(converter,
+		   const_cast<char **>(&s), &inremaining,
+		   &outbufcur, &outbufremaining) == ((size_t)-1))
+	    {
+	      // Some error conditions can be corrected.  There are three
+	      // reasons iconv can terminate abnormally:
+	      //
+	      //  (1) an invalid multibyte sequence occured.  We do not
+	      //      attempt to recover in this case.
+	      //
+	      //  (2) an incomplete multibyte sequence occured; as the
+	      //      input string is all the input we have, this reduces
+	      //      to case (1).
+	      //
+	      //  (3) no room left in the output buffer.  We respond by
+	      //      doubling the output buffer's size, or failing if
+	      //      it's doubled as far as it can go.
+
+	      if(errno != E2BIG)
+		{
+		  if(outbufremaining<outbufsize)
+		    out=wstring((wchar_t *) outbufhead.get(),
+				outbufsize-outbufremaining);
+		  return false;
+		}
+	      else
+		{
+		  auto_ptr<char> outbufnew(new char[outbufsize]);
+		  memcpy(outbufnew.get(), outbufhead.get(),
+			 outbufsize-outbufremaining);
+		  outbufremaining+=outbufsize;
+		  outbufsize*=2;
+		  // will deallocate outbufhead.
+		  outbufhead=outbufnew;
+		}
+	    }
+	  else
+	    // if this fails, my understanding of iconv is wrong: the
+	    // iconv docs say that if it doesn't fail, then the whole
+	    // input sequence was converted.
+	    assert(inremaining==0);
+	}
+
+      out=wstring((wchar_t *) outbufhead.get(), outbufsize-outbufremaining);
+      return true;
+    }
+  catch(bad_alloc)
+    {
+      errno=ENOMEM;
+      return false;
+    }
+}
+

Added: branches/aptitude-0.3/aptitude/src/vscreen/transcode.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/vscreen/transcode.h	Sat Jun 25 15:45:42 2005
@@ -0,0 +1,42 @@
+// transcode.h                                      -*-c++-*-
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#ifndef TRANSCODE_H
+#define TRANSCODE_H
+
+#include <string>
+
+/** Convenience function to convert a multibyte encoding to wide
+ *  characters.  This is a wrapper around iconv.
+ *
+ *  \param s the string to decode
+ *  \param out the location to write the transcoded string
+ *  \param encoding the encoding of s; if \b null or unspecified,
+ *         the value of LC_CTYPE is used.
+ *
+ *  \return \b true if the entire string was successfully transcoded;
+ *  if transcoding failed, returns \b false and sets errno.
+ */
+bool transcode(const char *s,
+	       std::wstring &out,
+	       const char *encoding=NULL);
+
+// Note: would it be saner to express errors via exceptions?
+
+#endif // TRANSCODE_H