1 /*
  2  * CodePointSource.js - Source of code points from a string
  3  *
  4  * Copyright © 2013-2015, 2018, JEDLSoft
  5  *
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  *
 10  *     http://www.apache.org/licenses/LICENSE-2.0
 11  *
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  *
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 
 20 var isPunct = require("./isPunct.js");
 21 var NormString = require("./NormString.js");
 22 
 23 /**
 24  * @class
 25  * Represents a buffered source of code points. The input string is first
 26  * normalized so that combining characters come out in a standardized order.
 27  * If the "ignorePunctuation" flag is turned on, then punctuation
 28  * characters are skipped.
 29  *
 30  * @constructor
 31  * @private
 32  * @param {NormString|string} str a string to get code points from
 33  * @param {boolean} ignorePunctuation whether or not to ignore punctuation
 34  * characters
 35  */
 36 var CodePointSource = function(str, ignorePunctuation) {
 37     this.chars = [];
 38     // first convert the string to a normalized sequence of characters
 39     var s = (typeof(str) === "string") ? new NormString(str) : str;
 40     this.it = s.charIterator();
 41     this.ignorePunctuation = typeof(ignorePunctuation) === "boolean" && ignorePunctuation;
 42 };
 43 
 44 /**
 45  * Return the first num code points in the source without advancing the
 46  * source pointer. If there are not enough code points left in the
 47  * string to satisfy the request, this method will return undefined.
 48  *
 49  * @param {number} num the number of characters to peek ahead
 50  * @return {string|undefined} a string formed out of up to num code points from
 51  * the start of the string, or undefined if there are not enough character left
 52  * in the source to complete the request
 53  */
 54 CodePointSource.prototype.peek = function(num) {
 55     if (num < 1) {
 56         return undefined;
 57     }
 58     if (this.chars.length < num && this.it.hasNext()) {
 59         for (var i = 0; this.chars.length < 4 && this.it.hasNext(); i++) {
 60             var c = this.it.next();
 61             if (c && !this.ignorePunctuation || !isPunct(c)) {
 62                 this.chars.push(c);
 63             }
 64         }
 65     }
 66     if (this.chars.length < num) {
 67         return undefined;
 68     }
 69     return this.chars.slice(0, num).join("");
 70 };
 71 /**
 72  * Advance the source pointer by the given number of code points.
 73  * @param {number} num number of code points to advance
 74  */
 75 CodePointSource.prototype.consume = function(num) {
 76     if (num > 0) {
 77         this.peek(num); // for the iterator to go forward if needed
 78         if (num < this.chars.length) {
 79             this.chars = this.chars.slice(num);
 80         } else {
 81             this.chars = [];
 82         }
 83     }
 84 };
 85 
 86 module.exports = CodePointSource;
 87