40
edits
(→Buffer) |
No edit summary |
||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
:''See also: the [[/Show of hands/]] as well as the [[/Unpacking/]] and [[/Essay/]] portions which were removed.'' | |||
This proposal was written by Daniel Friesen as an alternative to the [[ServerJS/Binary/B|Binary/B]] proposal. | This proposal was written by Daniel Friesen as an alternative to the [[ServerJS/Binary/B|Binary/B]] proposal. | ||
Line 6: | Line 7: | ||
anything remotely resembling an Array. | anything remotely resembling an Array. | ||
One goal of this proposal is interoperability between Strings and Blobs. That is, like Binary/B, this proposal aims to permit a class of generic algorithms that can operate on both Blob and String through a generic intersection between their API's. However, unlike Binary/B, this proposal avoids things that seem counter-intuitive, like putting .charAt on a Blob, a byte collection. Instead, this proposal augments String with a .valueAt so that method can be used generically on both Blob and String. | One goal of this proposal is interoperability between Strings and Blobs. That is, like Binary/B, this proposal aims to permit a class of generic algorithms that can operate on both Blob and String through a generic intersection between their API's. However, unlike Binary/B, this proposal avoids things that seem counter-intuitive, like putting .charAt on a Blob, a byte collection. Instead, this proposal augments String with a .valueAt so that method can be used generically on both Blob and String and a Buffer system which works on either type. | ||
This proposal is based off of API's drafted for MonkeyScript ([http://draft.monkeyscript.org/api/_std/Blob.html Blob] [http://draft.monkeyscript.org/api/_std/Buffer.html Buffer]). | This proposal is based off of API's drafted for MonkeyScript ([http://draft.monkeyscript.org/api/_std/Blob.html Blob] [http://draft.monkeyscript.org/api/_std/Buffer.html Buffer]). | ||
Line 21: | Line 22: | ||
:A type of list which manages a list of items. These items are not related to one another in any way other than their inclusion in the list and do not need to be of the same type. | :A type of list which manages a list of items. These items are not related to one another in any way other than their inclusion in the list and do not need to be of the same type. | ||
:A key importance is an Array is a loose collection of items, these items do not have any sort of fixed unit to them. | :A key importance is an Array is a loose collection of items, these items do not have any sort of fixed unit to them. | ||
;memcopy | |||
:Where used memcopy is used it refers to the technique of copying memory as directly as possible from one source to another. At the very least this refers to copying from A to B without creating an intermediate Blob. | |||
Where "as if by" is used in the spec the result is meant, the algorithm should not be affected by changes to the class' prototype. | Where "as if by" is used in the spec the result is meant, the algorithm should not be affected by changes to the class' prototype. | ||
Line 43: | Line 46: | ||
:You can give multiple arguments to these methods, but then you are no longer working with your lists in the same way. | :You can give multiple arguments to these methods, but then you are no longer working with your lists in the same way. | ||
: | : | ||
:There is another name which does fit this kind of operation, "Append" (Side note, Wrench.js does .append to | :There is another name which does fit this kind of operation, "Append" (Side note, Wrench.js does add .append to Array). Using [1,2,3].append([4,5,6]); DOES push 4, 5, and 6 onto the array creating the array [1,2,3,4,5,6]. | ||
== Prior art == | == Prior art == | ||
Java's [http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html java.lang.StringBuffer] is a very good reference for prior art. It is made for Strings rather than bytes, but nonetheless it's a api designed solely for the purpose of mutation of a string, not one designed for one purpose and hacked to suit another. | Java's [http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html java.lang.StringBuffer] is a very good reference for prior art. It is made for Strings rather than bytes, but nonetheless it's a api designed solely for the purpose of mutation of a string, not one designed for one purpose and hacked to suit another. | ||
Java's StringBuffer works using by append[ing](), insert[ing](), strings to grow the buffer. .delete() removes portions of the buffer, .indexOf() and .lastIndexOf() can search, .replace() and .reverse() are available, .length() shows the length of the data itself, .capacity() shows the current amount of memory allocated, and .substring can grab a substring from the StringBuffer. | |||
== The API == | == The API == | ||
Line 69: | Line 62: | ||
Most of the blob methods work on blobish data, rather than flat blobs. This means that the argument is treated as if it were passed through Blob(), thus .indexOf(255); is the same as if you had done .indexOf(Blob(255)), so you do not need to explicitly convert everything into a blob. | Most of the blob methods work on blobish data, rather than flat blobs. This means that the argument is treated as if it were passed through Blob(), thus .indexOf(255); is the same as if you had done .indexOf(Blob(255)), so you do not need to explicitly convert everything into a blob. | ||
Note that unlike String, Blob is not defined as a primitive datatype by ECMA, this means that typeof will never return 'blob' and all blobs will be objects unlike strings which are normally primitives. Blob works with and without the new constructor and acts the same. It is recommended to use the `Blob()` form | |||
;[new] Blob(); | ;[new] Blob(); | ||
Line 83: | Line 78: | ||
;blob.length; | ;blob.length; | ||
:Returns the length of the blob. This is immutable. | :Returns the length of the blob. This is immutable. | ||
;blob.contentConstructor; | |||
:Returns Blob to indicate this has binary content. | |||
;blob[index]; // Optional | ;blob[index]; // Optional | ||
Line 129: | Line 127: | ||
:This method is optional, it should be included if the interpreter being used supports .toSource() on it's various objects and types. | :This method is optional, it should be included if the interpreter being used supports .toSource() on it's various objects and types. | ||
:Returns a representation of the blob in the format "(Blob([]))" or "(new Blob([]))". If the blob has content in it the string should contain integers 0..255 representing the blob such that if evaluated (calling the correct Blob function) would return a blob with the same content. | :Returns a representation of the blob in the format "(Blob([]))" or "(new Blob([]))". If the blob has content in it the string should contain integers 0..255 representing the blob such that if evaluated (calling the correct Blob function) would return a blob with the same content. | ||
=== Buffer === | === Buffer === | ||
Line 176: | Line 163: | ||
:When length is set the buffer is dynamically resized. If shrunk it is truncated to size discarding items from the end. If grown the buffer is padded with 0 bytes for binary, and '\0' (null characters) for text. | :When length is set the buffer is dynamically resized. If shrunk it is truncated to size discarding items from the end. If grown the buffer is padded with 0 bytes for binary, and '\0' (null characters) for text. | ||
;buf. | ;buf.contentConstructor; | ||
: | :Returns Blob from a BlobBuffer to indicate it has binary content, and String from StringBuffer to indicate it has text content. Implementations should make an effort to make this readonly. | ||
;buf[index]; | ;buf[index]; | ||
Line 185: | Line 171: | ||
;buf.append(data); | ;buf.append(data); | ||
:Append a chunk of data to the end of the buffer growing it by <code>data.length</code>. | :Append a chunk of data to the end of the buffer growing it by <code>data.length</code>. If data is another Buffer memcopy should be used. | ||
;buf.insert(data, index); | ;buf.insert(data, index); | ||
:Insert a chunk of data into a buffer growing it by <code>data.length</code> and shifting the data to the right of the specified index towards the end of the buffer. | :Insert a chunk of data into a buffer growing it by <code>data.length</code> and shifting the data to the right of the specified index towards the end of the buffer. If data is another Buffer memcopy should be used. | ||
;buf.clear(start, length); | ;buf.clear(start, length); | ||
Line 200: | Line 186: | ||
;buf.splice(offset, length, data, ...); | ;buf.splice(offset, length, data, ...); | ||
:Remove a section of the buffer and insert chunks of data starting from the place it was removed from. | :Remove a section of the buffer and insert chunks of data starting from the place it was removed from. If data is another Buffer memcopy should be used. | ||
;buf.slice(); | ;buf.slice(); | ||
Line 206: | Line 192: | ||
;buf.slice(start, end); | ;buf.slice(start, end); | ||
:Extract a subsection of the buffer and return it as a new sequence. (Behaves the same as the string and blob counterparts) | :Extract a subsection of the buffer and return it as a new sequence. (Behaves the same as the string and blob counterparts) | ||
;buf.copy(data, offset, length, [dataOffset]); | |||
:Uses memcopy to copy a section of data directly into buf. data may either be another buffer of the same type, or a sequence (String/Blob) of same type as indicated by contentConstructor. | |||
;buf.split(); | ;buf.split(); | ||
Line 215: | Line 204: | ||
;buf.lastIndexOf(sequence, offset=0); | ;buf.lastIndexOf(sequence, offset=0); | ||
:Returns the index within the calling buffer object of the first or last (depending on which method is used) occurrence of the specified value, or -1 if not found. | :Returns the index within the calling buffer object of the first or last (depending on which method is used) occurrence of the specified value, or -1 if not found. | ||
;buf.valueOf(); | ;buf.valueOf(); | ||
Line 226: | Line 212: | ||
=== String extensions === | === String extensions === | ||
These extensions may be optional, however it would be ideal if implementations added these prototypes to the standard objects. Implementations may chose how to implement these (load binary themselves beforehand, prototype methods that use require('binary') within them, etc...) | These extensions may be optional, however it would be ideal if implementations added these prototypes to the standard objects. Implementations may chose how to implement these (load binary themselves beforehand, prototype methods that use require('binary') within them, etc...) | ||
;string.contentConstructor; | |||
:Returns String to indicate this has text content. | |||
;string.toBlob(toCharset); | ;string.toBlob(toCharset); | ||
Line 237: | Line 226: | ||
:An alias for string.charCodeAt(index); | :An alias for string.charCodeAt(index); | ||
:The point of this prototype is so that (string or blob).codeAt(index); may be used independently of whether the sequence is a string or a blob. This will allow strings to maintain .charCodeAt and blobs to maintain .byteCodeAt without returning unintuitive results. | :The point of this prototype is so that (string or blob).codeAt(index); may be used independently of whether the sequence is a string or a blob. This will allow strings to maintain .charCodeAt and blobs to maintain .byteCodeAt without returning unintuitive results. | ||
== Abstract API == | |||
One of the primary focuses was interoperability between Strings and Blobs so that abstract algorithms could be written which work on either strings or blobs. | |||
The entire Buffer api was designed for this purpose, and the following methods on String and Blob are usable in abstract programming: | |||
* seq.length; | |||
* seq.contentConstructor (can be used as seq.contentConstructor() to return an empty seq of the same type) | |||
* seq.valueAt(idx); // Sequence at index | |||
* seq.codeAt(idx); // Number at index | |||
* seq.valueOf(); // Returns the same seq (on a buffer returns the equiv Blob or String) | |||
* seq.indexOf(seq, [off]); and seq.lastIndexOf(seq, [off]); // finding the location of a subsequence | |||
* seq.concat(...seq); // combining sequences together | |||
* seq.slice(begin, end); // extracting a portion of a sequence | |||
* seq.split(sep, [limit]); // split up a sequence using another sequence as a separator | |||
== General requirements == | == General requirements == | ||
Line 254: | Line 257: | ||
* For now I've ignored things like .eq/equals, .lt, gt, etc... do note that Rhino actually implements .equals on String already. Also if we do add these things to blob we should probably implement the same on string. | * For now I've ignored things like .eq/equals, .lt, gt, etc... do note that Rhino actually implements .equals on String already. Also if we do add these things to blob we should probably implement the same on string. | ||
* Aristid Breitkreuz notes Buffer could be moved to IO. | * Aristid Breitkreuz notes Buffer could be moved to IO. | ||
== Relevant discussion == | |||
* http://groups.google.com/group/serverjs/browse_thread/thread/3b0a3a20a67987d8 |
edits