(plen (string-length prefix)))
(if (not (<= 1 length (- 70 plen)))
(error:bad-range-argument length 'RANDOM-MIME-BOUNDARY-STRING))
- (let ((s
- (call-with-output-string
- (lambda (port)
- (write-string prefix port)
- (let ((context (encode-base64:initialize port #f)))
- (let ((n (* (integer-ceiling (- length 2) 4) 3)))
- (encode-base64:update context (random-byte-vector n) 0 n))
- (encode-base64:finalize context)))))
- (n (+ plen length)))
- (if (fix:> (string-length s) n)
- (set-string-maximum-length! s n))
- s)))
+ (string-head! (call-with-output-string
+ (lambda (port)
+ (write-string prefix port)
+ (let ((context (encode-base64:initialize port #f)))
+ (let ((n (* (integer-ceiling (- length 2) 4) 3)))
+ (encode-base64:update context
+ (random-byte-vector n) 0 n))
+ (encode-base64:finalize context))))
+ (+ plen length))))
\f
;;;; Attachment browser
(set-interrupt-enables! mask)
result)))))
-(define (edwin-set-string-maximum-length! string n-chars)
- (if (not (string? string))
- (error:wrong-type-argument string "string" 'SET-STRING-MAXIMUM-LENGTH!))
- (if (not (fix:fixnum? n-chars))
- (error:wrong-type-argument n-chars "fixnum" 'SET-STRING-MAXIMUM-LENGTH!))
- (if (not (and (fix:>= n-chars 0)
- (fix:< n-chars
- (fix:lsh (fix:- (system-vector-length string) 1)
- (fix:- 0 (chars-to-words-shift))))))
- (error:bad-range-argument n-chars 'SET-STRING-MAXIMUM-LENGTH!))
- (let ((mask (set-interrupt-enables! interrupt-mask/none)))
- ((ucode-primitive primitive-object-set! 3)
- string
- 0
- ((ucode-primitive primitive-object-set-type 2)
- (ucode-type manifest-nm-vector)
- (fix:+ 1 (chars->words (fix:+ n-chars 1)))))
- (set-string-length! string (fix:+ n-chars 1))
- (string-set! string n-chars #\nul)
- (set-string-length! string n-chars)
- (set-interrupt-enables! mask)
- unspecific))
-
(define string-allocate
(if (compiled-procedure? edwin-string-allocate)
edwin-string-allocate
(ucode-primitive string-allocate)))
-
-(define set-string-maximum-length!
- (if (compiled-procedure? edwin-set-string-maximum-length!)
- edwin-set-string-maximum-length!
- (ucode-primitive set-string-maximum-length!)))
\f
(define (%substring-move! source start-source end-source
target start-target)
(string-allocate 1)
(string-hash-mod 2)
(string-length 1)
- (string-maximum-length 1)
(string-ref 2)
(string-set! 3)
(string? 1)
(define (string-head string end)
(guarantee-string string 'STRING-HEAD)
- (guarantee-string-index end 'STRING-HEAD)
+ (guarantee-substring-end-index end (string-length string) 'STRING-HEAD)
(%string-head string end))
-(declare (integrate-operator %string-head))
-(define (%string-head string end)
+(define-integrable (%string-head string end)
(%substring string 0 end))
-(define (%truncate-string! string end)
- (let-syntax ((chars-to-words-shift
- (sc-macro-transformer
- (lambda (form environment)
- form environment
- ;; This is written as a macro so that the shift will be a constant
- ;; in the compiled code.
- ;; It does not work when cross-compiled!
- (let ((chars-per-word (vector-ref (gc-space-status) 0)))
- (case chars-per-word
- ((4) -2)
- ((8) -3)
- (else (error "Can't support this word size:" chars-per-word))))))))
-
- (if (not (and (fix:>= end 0)
- (fix:< end
- (fix:lsh (fix:- (system-vector-length string) 1)
- (fix:- 0 (chars-to-words-shift))))))
- (error:bad-range-argument end 'STRING-HEAD!))
- (let ((mask (set-interrupt-enables! interrupt-mask/none)))
- ((ucode-primitive primitive-object-set! 3)
- string
- 0
- ((ucode-primitive primitive-object-set-type 2)
- (ucode-type manifest-nm-vector)
- (fix:+ 1 (chars->words (fix:+ end 1)))))
- (set-string-length! string (fix:+ end 1))
- (string-set! string end #\nul)
- (set-string-length! string end)
- (set-interrupt-enables! mask)
- string)))
-
-(define %string-head!
- (if (compiled-procedure? %truncate-string!)
- %truncate-string!
- %string-head))
-
-(define (string-head! string end)
- (guarantee-string string 'STRING-HEAD!)
- (guarantee-string-index end 'STRING-HEAD!)
- (%string-head! string end))
-
(define (string-tail string start)
(guarantee-string string 'STRING-TAIL)
- (guarantee-string-index start 'STRING-TAIL)
+ (guarantee-substring-start-index start (string-length string) 'STRING-TAIL)
(%substring string start (string-length string)))
(define (string-copy string)
(%substring-move! string 0 size result 0)
result)))
\f
+(define (string-head! string end)
+ (guarantee-string string 'STRING-HEAD!)
+ (guarantee-substring-end-index end (string-length string) 'STRING-HEAD!)
+ (%string-head! string end))
+
+(define %string-head!
+ (let ((reuse
+ (lambda (string end)
+ (let ((mask (set-interrupt-enables! interrupt-mask/none)))
+ ((ucode-primitive primitive-object-set! 3)
+ string
+ 0
+ ((ucode-primitive primitive-object-set-type 2)
+ (ucode-type manifest-nm-vector)
+ (fix:+ 1 (%octets->words (fix:+ end 1)))))
+ (set-string-length! string (fix:+ end 1))
+ (string-set! string end #\nul)
+ (set-string-length! string end)
+ (set-interrupt-enables! mask)
+ string))))
+ (if (compiled-procedure? reuse)
+ reuse
+ %string-head)))
+
+(define (string-maximum-length string)
+ (guarantee-string string 'STRING-MAXIMUM-LENGTH)
+ (%string-maximum-length string))
+
+(define-integrable (%string-maximum-length string)
+ (fix:- (%octets-maximum-length string) 1))
+
+(define-integrable (%octets-maximum-length octets)
+ (fix:lsh (fix:- (system-vector-length octets) 1)
+ %words->octets-shift))
+
+(define-integrable (%octets->words n-octets)
+ (fix:lsh (fix:+ n-octets (fix:not (fix:lsh -1 %words->octets-shift)))
+ %octets->words-shift))
+
+(define-integrable %octets->words-shift
+ ((sc-macro-transformer
+ (lambda (form environment)
+ form environment
+ ;; This is written as a macro so that the shift will be a
+ ;; constant in the compiled code. It does not work when
+ ;; cross-compiled!
+ (let ((chars-per-word (vector-ref (gc-space-status) 0)))
+ (case chars-per-word
+ ((4) -2)
+ ((8) -3)
+ (else (error "Can't support this word size:" chars-per-word))))))))
+
+(define-integrable %words->octets-shift
+ (fix:- 0 %octets->words-shift))
+\f
(define (string . objects)
(%string-append (map ->string objects)))