1 jls.loader.provide('jls.lang.CharBuffer');
  2 
  3 jls.loader.require('jls.lang.Buffer');
  4 jls.loader.require('jls.lang.ByteBuffer');
  5 jls.loader.require('jls.lang.IllegalArgumentException');
  6 jls.loader.require('jls.lang.BufferOverflowException');
  7 jls.loader.require('jls.lang.BufferUnderflowException');
  8 
  9 /**
 10  * @augments jls.lang.Buffer
 11  * @class The buffer class provides facilities to get and put datas from/to a native string.
 12  */
 13 jls.lang.CharBuffer = jls.lang.Class.create(jls.lang.Buffer, /** @lends jls.lang.CharBuffer.prototype */
 14 {
 15     initialize : function($super, barray, offset, length, limit, position) {
 16         if (! (barray instanceof _native.core.ByteArray)) {
 17             throw new jls.lang.Exception('Invalid barray argument (' + (typeof barray) + ')');
 18         }
 19         this._barray = barray;
 20         offset = offset || 0;
 21         var capacity = (typeof length != 'undefined') ? length : (this._barray.size() >>> 1) - offset;
 22         $super(capacity, limit, position, offset);
 23         this._byteOrder = jls.lang.CharBuffer.DEFAULT_BYTE_ORDER;
 24     },
 25     /**
 26      * Returns the native byte array of this buffer.
 27      * 
 28      * @returns {_native.core.ByteArray} The native byte array.
 29      */
 30     byteArray : function() {
 31         return this._barray;
 32     },
 33     /**
 34      * Free the associated byte array.
 35      * 
 36      * @returns {jls.lang.Buffer} This buffer.
 37      */
 38     free : function() {
 39         this._barray.free();
 40         return this;
 41     },
 42     /**
 43      * Creates a new buffer sharing the native string.
 44      * 
 45      * @returns {jls.lang.Buffer} The new buffer.
 46      */
 47     duplicate : function() {
 48         return new jls.lang.CharBuffer(this._barray, this._offset, this._capacity, this._limit, this._position);
 49     },
 50     /**
 51      * Creates a new buffer starting at the current position and with the remaining character.
 52      * 
 53      * @returns {jls.lang.Buffer} The new buffer.
 54      */
 55     slice : function() {
 56         return new jls.lang.CharBuffer(this._barray, this.position(), this.remaining());
 57     },
 58     /**
 59      * Puts a character into this buffer at the current position, and then increments the position.
 60      * 
 61      * @param {Number} c The character code to put.
 62      * @returns {jls.lang.Buffer} This buffer.
 63      */
 64     putChar : function(c) {
 65         if (this.remaining() < 1) {
 66             throw new jls.lang.BufferOverflowException();
 67         }
 68         if (typeof c == 'string') {
 69         	if (c.length != 1) {
 70                 throw new jls.lang.Exception('Invalid character argument');
 71         	}
 72         	c = c.charCodeAt(0);
 73         }
 74         var os = this.offset() * 2;
 75         if (this._byteOrder == jls.lang.Buffer.BIG_ENDIAN) {
 76             this._barray.put(os, (c >>> 8) & 0xff);
 77             this._barray.put(os + 1, c & 0xff);
 78         } else {
 79             this._barray.put(os, c & 0xff);
 80             this._barray.put(os + 1, (c >>> 8) & 0xff);
 81         }
 82         this._position++;
 83         return this;
 84     },
 85     /**
 86      * Gets a character from this buffer at a specified position.
 87      * 
 88      * @param {Number} index The position of the character to read.
 89      * @returns {Number} The character code.
 90      */
 91     getCharAt : function(index) {
 92         if (index > this.limit()) {
 93             throw new jls.lang.Exception('Index out of bound');
 94         }
 95         var value;
 96         var os = (this.getOffset() + index) * 2;
 97         if (this._byteOrder == jls.lang.Buffer.BIG_ENDIAN) {
 98             value = this._barray.get(os) << 8;
 99             value |= this._barray.get(os + 1);
100         } else {
101             value = this._barray.get(os);
102             value |= this._barray.get(os + 1) << 8;
103         }
104         return value;
105     },
106     /**
107      * Gets a character from this buffer at the current position, and then increments the position.
108      * 
109      * @returns {Number} The character code.
110      */
111     getChar : function() {
112         if (this.remaining() < 1) {
113             throw new jls.lang.BufferUnderflowException();
114         }
115         var value = this.getCharAt(this.position());
116         this._position++;
117         return value;
118     },
119     putString : function(s) {
120         if (this.remaining() < s.length) {
121             throw new jls.lang.BufferOverflowException();
122         }
123         // TODO wrap + memcpy?
124     	for (var i = 0; i < s.length; i++) {
125     		this.putChar(s.charCodeAt(i));
126     	}
127         return this;
128     },
129     getString : function(length) {
130         if (length) {
131             if (this.remaining() < length) {
132                 throw new jls.lang.BufferUnderflowException();
133             }
134         } else {
135             length = this.remaining();
136         }
137         /*var value = '';
138     	while (--length >= 0) {
139     		value += String.fromCharCode(this.getChar());
140     	}*/
141         var value = this._barray.getChars(this.position(), length);
142         this._position += length;
143         return value;
144     },
145     putBuffer : function(buffer, length) {
146 		length = length || buffer.remaining();
147         if (this.remaining() < length) {
148             throw new jls.lang.BufferOverflowException();
149         }
150         this._barray.memcpy(this.offset() * 2, buffer.byteArray(), buffer.position() * 2, length * 2);
151         this._position += length;
152         buffer.incrementPosition(length);
153         return this;
154     },
155     toNewString : function(length) {
156 		length = length || this.limit();
157     	if (this.getOffset() != 0) {
158             throw new jls.lang.Exception('Invalid CharBuffer (offset != 0)');
159     	}
160         return this._barray.toNewChars(length);
161     },
162     toString : function() {
163         return this.getString();
164     }
165 });
166 
167 Object.extend(jls.lang.CharBuffer, /** @lends jls.lang.CharBuffer */
168 {
169     /**
170      * Allocates a new buffer.
171      * 
172      * @param {Number} capacity The capacity of the character buffer.
173      * @returns {jls.lang.Buffer} The new buffer.
174      */
175     allocate : function(capacity, adoptable) {
176         return jls.lang.CharBuffer.wrap(new _native.core.ByteArray((capacity + 1) * 2, adoptable));
177     },
178     /**
179      * Wraps an existing native byte array into a new character buffer.
180      * 
181      * @param {_native.core.ByteArray} barray The native byte array to wrap.
182      * @param {Number} offset The offset of the byte array to use for this buffer.
183      * @param {Number} length The length of the buffer.
184      * @returns {jls.lang.Buffer} The new buffer.
185      */
186     wrap : function(barray, offset, length) {
187         if (typeof barray == 'string') {
188             length = length || barray.length;
189             //jls.logger.trace('CharBuffer.wrap("' + barray + '")');
190         	barray = new _native.core.ByteArray(barray);
191             //jls.logger.trace('CharBuffer.wrap(), barray.size(): ' + barray.size());
192             var buffer = new jls.lang.CharBuffer(barray, offset, length);
193             //jls.logger.trace('CharBuffer.wrap(), buffer.remaining(): ' + buffer.remaining() + ', buffer.capacity(): ' + buffer.capacity());
194             return buffer;
195         }
196         return new jls.lang.CharBuffer(barray, offset, length);
197     },
198     // Byte order constants.
199     DEFAULT_BYTE_ORDER : jls.lang.Buffer.LITTLE_ENDIAN
200 });
201 
202