class: ExternalStream
authorStefan Vogel <sv@exept.de>
Thu, 05 Feb 2015 19:16:24 +0100
changeset 17420 f0895ae69f69
parent 17419 664ffe1aa68e
child 17421 9f2dac6c6efb
class: ExternalStream changed: #initDefaultEOLMode #nextPutAll: #nextPutAll:startingAt:to: reenable #crlf end-of-line mode conversions DefaultEOLMode for windows is #nl, for backward and HTTP compatibility
ExternalStream.st
--- a/ExternalStream.st	Thu Feb 05 16:15:38 2015 +0100
+++ b/ExternalStream.st	Thu Feb 05 19:16:24 2015 +0100
@@ -1495,16 +1495,19 @@
 
 initDefaultEOLMode
     OperatingSystem isUNIXlike ifTrue:[
-	"/ unix EOL conventions
-	DefaultEOLMode := #nl
+        "/ unix EOL conventions
+        DefaultEOLMode := #nl
     ] ifFalse:[
-	OperatingSystem isVMSlike ifTrue:[
-	    "/ vms EOL conventions
-	    DefaultEOLMode := #cr
-	] ifFalse:[
-	    "/ msdos EOL conventions
-	    DefaultEOLMode := #crlf
-	]
+        OperatingSystem isVMSlike ifTrue:[
+            "/ vms EOL conventions
+            DefaultEOLMode := #cr
+        ] ifFalse:[
+            "/ msdos EOL conventions
+            "/ msdos uses #crlf. but we keep #nl here,
+            "/ otherwise sending HTTP request over sockets fails
+"/            DefaultEOLMode := #crlf
+            DefaultEOLMode := #nl
+        ]
     ]
 !
 
@@ -5929,28 +5932,78 @@
             }
 
             if (__isStringLike(aCollection)) {
+                char *stringP = __stringVal(aCollection);
                 len = __stringSize(aCollection);
 
-#if 0
-                if ((__INST(binary) != true)
-                 && (__INST(eolMode) != @symbol(nl))) {
-                    // see if there is a nl which needs to be translated; do it in chunks, if so
-                    if (memchr(__stringVal(aCollection), '\n', len) != NULL) {
+                if (__INST(binary) != true 
+                    && __INST(eolMode) != nil 
+                    && __INST(eolMode) != @symbol(nl)
+                    && memchr(stringP, '\n', len) != NULL) {
+                    // see if there is a \n which needs to be translated, 
+                    // replace \n if so
+
+                    char *end = stringP + len;
+                    char *sep = __INST(eolMode) == @symbol(crlf) ? "\r\n" : "\r";
+                    int sepLen = strlen(sep);
+                    int bufLen;
+                    char *buf, *endBuf, *sp, *dp;
+
+                    // estimate size of buffer - assume every 4th char is a separator
+                    bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen);
+                    buf = (char *)malloc(bufLen);
+                    if (buf == 0) {
+                        error = __mkSmallInteger(ENOMEM);
                         goto out;
                     }
+
+                    endBuf = buf + bufLen;
+
+                    for (sp = stringP, dp = buf; sp < end; sp++) {
+                        if (dp >= endBuf) {
+                            char *newBuf;
+
+                            bufLen = bufLen + ((bufLen/4) + 1) * sepLen;
+                            newBuf = (char *)realloc(buf, bufLen);
+                            if (newBuf == 0) {
+                                free(buf);        
+                                error = __mkSmallInteger(ENOMEM);
+                                goto out;
+                            }
+                            endBuf = newBuf + bufLen;
+                            dp = newBuf + (dp-buf);
+                            buf = newBuf;
+                        }
+
+                        if (*sp == '\n') {
+                            strcpy(dp, sep);
+                            dp += sepLen;
+                        } else {
+                            *dp++ = *sp;
+                        }
+                    }
+
+                    len = dp - buf;
+#ifdef WIN32
+                    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
+                        cnt = __win32_fwrite(buf, 1, len, f);
+                    } else
+#endif
+                    {
+                        __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType));
+                    }
+                    free(buf);
+                } else  {  // No EOL conversion needed
+#ifdef WIN32
+                    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
+                        cnt = __win32_fwrite(stringP, 1, len, f);
+                    } else
+#endif
+                    {
+                        o_offs = stringP - (char *)__InstPtr(aCollection);
+                        __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
+                    }
                 }
-#endif
-
-#ifdef WIN32
-                if ((f == __win32_stdout()) || (f == __win32_stderr())) {
-                    cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f);
-                } else
-#endif
-                {
-                    o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
-                    __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
-                }
-            } else {
+            } else {   // Not a String
                 if (__INST(binary) == true) {
                     INT offs;
 
@@ -5972,10 +6025,11 @@
                         o_offs += offs;
                         __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
                     }
-                } else
+                } else  // Not binary mode
                     goto out;
             }
 
+            // Now check for errors
             if (cnt == len) {
                 if (__isSmallInteger(__INST(position))) {
                     INT np = __intVal(__INST(position)) + len;
@@ -5987,6 +6041,7 @@
                 }
                 RETURN (self);
             }
+            fprintf(stderr, "cnt=%d len=%d\n", cnt, len);    
             error = __mkSmallInteger(__threadErrno);
         }
     }
@@ -6036,6 +6091,8 @@
                 RETURN(self);
             }
             if (__isStringLike(aCollection)) {
+                char *stringP;
+
                 len = __stringSize(aCollection);
                 if (iStop > len) {
                     RETURN(self);
@@ -6043,27 +6100,77 @@
                 if (iStop > len)
                     iStop = len;
                 len = iStop - iStart + 1;
-
-#if 0
-                if ((__INST(binary) != true)
-                 && (__INST(eolMode) != @symbol(nl))) {
-                    // see if there is a nl which needs to be translated; do it in chunks, if so
-                    if (memchr(__stringVal(aCollection)+iStart-1, '\n', len) != NULL) {
+                stringP = __stringVal(aCollection) + iStart - 1;
+
+                if (__INST(binary) != true 
+                    && __INST(eolMode) != nil 
+                    && __INST(eolMode) != @symbol(nl)
+                    && memchr(stringP, '\n', len) != NULL) {
+                    // see if there is a \n which needs to be translated, 
+                    // replace \n if so
+
+                    char *end = stringP + len;
+                    char *sep = __INST(eolMode) == @symbol(crlf) ? "\r\n" : "\r";
+                    int sepLen = strlen(sep);
+                    int bufLen;
+                    char *buf, *endBuf, *sp, *dp;
+
+                    // estimate size of buffer - assume every 4th char is a separator
+                    bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen);
+                    buf = (char *)malloc(bufLen);
+                    if (buf == 0) {
+                        error = __mkSmallInteger(ENOMEM);
                         goto out;
                     }
+
+                    endBuf = buf + bufLen;
+
+                    for (sp = stringP, dp = buf; sp < end; sp++) {
+                        if (dp >= endBuf) {
+                            char *newBuf;
+
+                            bufLen = bufLen + ((bufLen/4) + 1) * sepLen;
+                            newBuf = (char *)realloc(buf, bufLen);
+                            if (newBuf == 0) {
+                                free(buf);        
+                                error = __mkSmallInteger(ENOMEM);
+                                goto out;
+                            }
+                            endBuf = newBuf + bufLen;
+                            dp = newBuf + (dp-buf);
+                            buf = newBuf;
+                        }
+
+                        if (*sp == '\n') {
+                            strcpy(dp, sep);
+                            dp += sepLen;
+                        } else {
+                            *dp++ = *sp;
+                        }
+                    }
+
+                    len = dp - buf;
+#ifdef WIN32
+                    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
+                        cnt = __win32_fwrite(buf, 1, len, f);
+                    } else
+#endif
+                    {
+                        __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType));
+                    }
+                    free(buf);
+                } else  {  // No EOL conversion needed
+#ifdef WIN32
+                    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
+                        cnt = __win32_fwrite(stringP, 1, len, f);
+                    } else
+#endif
+                    {
+                        o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
+                        __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType));
+                    }
                 }
-#endif
-
-#ifdef WIN32
-                if ((f == __win32_stdout()) || (f == __win32_stderr())) {
-                    cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f);
-                } else
-#endif
-                {
-                    o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
-                    __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType));
-                }
-            } else {
+            } else {  // Not a string
                 if (__INST(binary) == true) {
                     int offs;
 
@@ -6266,11 +6373,11 @@
 !ExternalStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.401 2015-02-05 13:07:09 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.402 2015-02-05 18:16:24 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.401 2015-02-05 13:07:09 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.402 2015-02-05 18:16:24 stefan Exp $'
 ! !