Re: JavaXPCOM: How to handle unsigned 8-bit values?
Michal Ceresna <[email protected]>
| Newsgroups | gmane.comp.mozilla.devel.java |
|---|---|
| Message-ID | <200704241044.10497.michal.ceresna__17420.1202615679$1177404499$gmane$org@gmail.com> |
On Monday 23 April 2007, Javier Pedemonte wrote:
Hello Javier,
> 3) Promote everything but 'octet' values. This way, the user doesn't
> need to worry about unsigned values, except for byte. And since byte
> arrays are often used for passing around data, there is no need to first
> copy the data to a short array.
Sounds good.
All usages of 'octet' seem to occur only in array declarations.
I would even suggest also to not promote PRUint8[] arrays.
(see the usage patterns below)
best regards,
Michal
Various declaration patterns of primitive-type arrays in IDL interfaces:
unsigned long:
mozIStorageStatement.idl: [array,size_is(aCount),retval] out unsigned long aIndexes);
long:
nsIAccessibleTable.idl: [retval, array, size_is(columnsSize)] out longcolumns);
nsIAccessibleTable.idl: [retval, array, size_is(rowsSize)] out long rows);
PRInt64:
nsINavHistoryService.idl: [retval,array,size_is(count)] out PRInt64 folders);
nsINavHistoryService.idl: void setFolders([const,array, size_is(folderCount)] in PRInt64 folders,
PRInt32:
nsINavHistoryService.idl: [retval,array,size_is(groupCount)] out PRUint32 groupingMode);
nsINavHistoryService.idl: void setGroupingMode([const,array,size_is(groupCount)] in PRUint32 groupingMode,
PRUnichar:
nsIUnicharInputStream.idl: [noscript] unsigned long read([array, size_is(aCount)] in PRUnichar aBuf,
nsIUnicharOutputStream.idl: [const, array, size_is(aCount)] inPRUnichar c);
PRUint8:
gfxIImageFrame.idl: void getImageData([array, size_is(length)] out PRUint8 bits, out unsigned long length);
gfxIImageFrame.idl: void setImageData([array, size_is(length), const] in PRUint8 data,
gfxIImageFrame.idl: void getAlphaData([array, size_is(length)] out PRUint8 bits, out unsigned long length);
gfxIImageFrame.idl: void setAlphaData([array, size_is(length), const] in PRUint8 data,
imgIEncoder.idl: void initFromData([array, size_is(length), const] in PRUint8 data,
nsIBinaryInputStream.idl: [array, size_is(aLength), retval] out PRUint8 aBytes);
nsIBinaryOutputStream.idl: void writeByteArray([array, size_is(aLength)] in PRUint8 aBytes,
octet:
mozIStorageValueArray.idl: void getBlob(in unsigned long aIndex, out unsigned long aDataSize, [array,size_is(aDataSize)] out octet aData);
nsIAnnotationService.idl: [const,array,size_is(aDataLen)] in octet aData,
nsIAnnotationService.idl: [array,size_is(aDataLen)] out octet aData,nsICRLManager.idl: void importCrl([array, size_is(length)] in octet data,
nsICollation.idl: [array,size_is(outLen)] out octet key,
nsICollation.idl: [noscript] long compareRawSortKey([const,array,size_is(len1)] in octet key1, in unsigned long len1,
nsICollation.idl: [const,array,size_is(len2)] in octet key2, in unsigned long len2);
nsIContentSniffer.idl: [const,array,size_is(aLength)] in octet aData,
nsICryptoHash.idl: void update([const, array, size_is(aLen)] in octet aData,in unsigned long aLen);
nsIDOMParser.idl: nsIDOMDocument parseFromBuffer([const,array,size_is(bufLen)]in octet buf,
nsIFaviconService.idl: [const,array,size_is(aDataLen)] in octet aData,
nsIKeyModule.idl: [const, array, size_is(aWrappedKeyLen)] in octet aWrappedKey,
nsIScriptableUConv.idl: AString convertFromByteArray([const,array,size_is(aCount)] in octet aData,
nsIScriptableUConv.idl: [array, size_is(aLen),retval] out octet aData);
nsIStreamCipher.idl: [const, array, size_is(aIVLen)] in octet aIV,
nsIStreamCipher.idl: void update([const, array, size_is(aLen)] in octet aData, in unsigned long aLen);
nsIStreamLoader.idl: [const,array,size_is(resultLength)] in octet result);
nsIWebBrowserStream.idl: void appendToStream([const, array, size_is(aLen)] in octet aData,
nsIX509Cert.idl: [retval, array, size_is(length)] out octet data);
nsIX509CertDB.idl: void importCertificates([array, size_is(length)] in octet data,
nsIX509CertDB.idl: void importEmailCertificate([array, size_is(length)] in octet data,
nsIX509CertDB.idl: void importServerCertificate([array, size_is(length)] in octet data,
nsIX509CertDB.idl: void importUserCertificate([array, size_is(length)] in octet data,
Used command:
grep 'array,[ ]*size.*\(in\|out\)' *.idl | grep -v '[ \t]*\(#\|\*\|//\)' | grep -v 'array, *size_is(\w*)\(,[ ]*retval\)*\(,[ ]*const\)*] \(in\|out\) \(nsI\|jsdI\|wstring\|string\|octet\|PRUint8\|PRUnichar\|PRUint32\|PRInt64\long\|unsigned long\)' | less
> Java doesn't support unsigned values. However, many of the Mozilla
> interfaces take or return unsigned values. The solution in JavaXPCOM
> has been to 'promote' the unsigned types to the next larger type in
> Java, such that the larger type can handle the full range of the
> unsigned type. So, for example, a Mozilla interface that returns an
> 'unsigned int' in Java is defined to return a 'long'.
>
> But this doesn't work that well for 8-bit (byte) values, since byte
> arrays are often used to pass around large chunks of data. Take for
> example the nsIWebBrowserStream.appendToStream() function
> (http://mxr.mozilla.org/mozilla/source/embedding/browser/webBrowser/nsIWebB
>rowserStream.idl#73). According to the XPIDL file, it takes an 'octet' array
> of data
> ('octet' is defined in XPIDL as an unsigned 8-bit value).
>
> In Java, it would be natural to want to do something like this:
> String htmlData = ...;
> byte[] bytes = htmlData.getBytes("UTF-8");
> webBrowserStream.appendToStream(bytes, bytes.length);
>
> However, since 'octet' is promoted to the Java 'short', we must first
> convert the byte array returned by getBytes() to a short array, before
> passing it to appendToStream(). Of course, under the covers, JavaXPCOM
> will then convert the short array to a C++ byte array, meaning that in
> the end, this array is converted twice to essentially get what we
> started with.
>
>
> I see three ways that JavaXPCOM could handle unsigned values:
>
> 1) Promote every XPIDL type to the next larger Java type. This makes it
> easiest on the JavaXPCOM user, since they can see the full range of
> values and not have to worry about tricks for getting the 'unsigned'
> value. However, for 'octet' arrays, it may require to the user to go
> through an extra step, as illustrated above.
>
> 2) Don't promote anything; C++ type == Java type. This avoids the issue
> above. However, the user must now take care when working with unsigned
> parameters. In most cases, since they want the actual value, the user
> will do the unsigned conversion themselves by putting the value in the
> next larger type.
>
> 3) Promote everything but 'octet' values. This way, the user doesn't
> need to worry about unsigned values, except for byte. And since byte
> arrays are often used for passing around data, there is no need to first
> copy the data to a short array.
>
>
> I prefer the 3rd option. What does everyone else here think?
>
>
> javier pedemonte
> _______________________________________________
> dev-tech-java mailing list
> [email protected]
> https://lists.mozilla.org/listinfo/dev-tech-java