Hi,

GNUstep's NSString currently lacks getBytes:maxLength:usedLength:encoding:options:range:remainingRange:

(added in OS X 10.5).

I wanted to implement this function, but GSFromUnicode()'s behavior is not the best fit for this method:

1) it fails if the output buffer is too small - we don't want that in this case 2) it doesn't tell you how many input characters were converted (which is understandable because of 1)

So I decided to use iconv() directly, which has a pitfall. I'd need to access static members (EntrySupported) of Unicode.m to know the iconv encoding's name etc. So I guess the iconv-related code (as attached) should be moved into Unicode.m.

===============

So I have a question: is it OK to write a function with declaration:

BOOL GSFromUnicodePartial(NSStringEncoding enc, int options, unichar **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);

that wouldn't suffer from 1) and 2) and add it into Source/Additions/Unicode.m next to GSFromUnicode()?

--
Luboš Doležel
Index: NSString.m
===================================================================
--- NSString.m	(revision 36703)
+++ NSString.m	(working copy)
@@ -1712,6 +1712,91 @@
 }
 
 /**
+ * Retrieves a part of the string while converting it to a specified encoding
+ */
+- (BOOL) getBytes: (void*)buffer
+        maxLength: (NSUInteger)maxBufferCount
+       usedLength: (NSUInteger*)usedBufferCount
+         encoding: (NSStringEncoding)encoding
+          options: (NSStringEncodingConversionOptions)options
+            range: (NSRange)range
+   remainingRange: (NSRangePointer)leftover
+{
+#ifdef HAVE_ICONV
+  unichar *chars;
+  struct _strenc_	*encInfo;
+  iconv_t	cd;
+  char	*inbuf;
+  char	*outbuf;
+  size_t	inbytesleft;
+  size_t	outbytesleft;
+  size_t	icresult;
+  const char	*enc;
+
+  encInfo = EntrySupported(encoding);
+
+  if (!encInfo)
+    return NO;
+
+  enc = encInfo->iconv;
+
+  if (options & NSStringEncodingConversionAllowLossy)
+    enc = encInfo->lossy;
+  cd = iconv_open(estr, UNICODE_ENC);
+
+  if (cd == (iconv_t)-1)
+	{
+      NSLog(@"[NSString getBytes]: No iconv for encoding %@ tried to use %s",
+          GSPrivateEncodingName(encoding), enc);
+      return NO;
+	}
+
+  inbytesleft = range.length * sizeof(unichar);
+#if	GS_WITH_GC
+  chars = NSAllocateCollectable(inbytesleft, 0);
+#else
+  chars = NSZoneMalloc([self zone], inbytesleft);
+#endif
+
+  [self getCharacters: chars
+                range: range];
+
+  inbuf = (char*) chars;
+  outbuf = (unsigned char*) buffer;
+  outbytesleft = maxBufferCount;
+
+  icresult = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+
+#if !GS_WITH_GC
+  NSZoneFree([self zone], src);
+#endif
+
+  if (icresult == (iconv_t)-1 && errno != E2BIG)
+    return NO;
+
+  if (leftover != NULL)
+    {
+      if (inbytesleft > 0)
+        {
+          leftover->length = inbytesleft / sizeof(unichar);
+          leftover->location = range.location + range.length
+            - leftover->length;
+        }
+	  else
+        leftover->length = 0;
+    }
+
+  if (usedBufferCount != NULL)
+    *usedBufferCount = maxBufferCount - outbytesleft;
+
+  return YES;
+
+#else
+  return NO;
+#endif
+}
+
+/**
  * Constructs a new ASCII string which is a representation of the receiver
  * in which characters are escaped where necessary in order to produce a
  * version of the string legal for inclusion within a URL.<br />
_______________________________________________
Gnustep-dev mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/gnustep-dev

Reply via email to