text: // Copyright 2013 The Closure Library Authors. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //      http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS-IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  
  /**
   * @fileoverview Utility function for normalizing ďîàçŕìtíĉš.
   */
  goog.provide('goog.i18n.diacritics');
  
  goog.require('goog.asserts');
  
  
  /**
   * The diacritic versions of ascii characters are stored in the utf8 charcode
   * range of 192 through 382. This map was generated by creating a list of
   * those diacritics and generating a parallel map of their ascii counterparts.
   *   '*' == multi-char replacement (see MULTICHAR_REPLACEMENTS_)
   *   '^' == no replacement available
   * @const {string}
   * @private
   */
  goog.i18n.diacritics.REPLACEMENTS_ = 'AAAAAA*CEEEEIIIIDNOOOO' +
      'Ox0UUUUYpBaaaaaa*ceeeeiiiionooooo^ouuuuypyAaAaAaCcCcCcCcDdDdEeEeEeEeEeG' +
      'gGgGgGgHhHhIiIiIiIiIi**JjKkkLlLlLLLlttNnNnNnnNnOoOoOo**RrRrRrSsSsSsSsTt' +
      'TtttUuUuUuUuUuUuWwYyYZzZzZ';
  
  
  /**
   * Map from utf8 charcodes to their two-character ascii equivalents.
   * @enum {string}
   * @private
   */
  goog.i18n.diacritics.MULTICHAR_REPLACEMENTS_ = {
    198: 'AE',
    230: 'ae',
    306: 'IJ',
    307: 'ij',
    338: 'AE',
    339: 'ae'
  };
  
  
  /**
   * Given a utf8 charCode, finds the ascii equivalent if the charCode happens
   * to be a diacritic version of an ascii character. Œ = AE, ö = o, etc...
   * @param {number} charCode The utf8 charCode to find a replacement for.
   * @return {?string} null if there is no replacement, otherwise a 1 or 2 char
   *     replacement string.
   * @private
   */
  goog.i18n.diacritics.lookupReplacement_ = function(charCode) {
    // Check if the charCode is in the diacritic range.
    var MIN = 192, MAX = 382;
    if (charCode < MIN || charCode > MAX) {
      return null;
    }
    // Check to see if we have a multichar replacement.
    var replacement = goog.i18n.diacritics.MULTICHAR_REPLACEMENTS_[charCode];
    if (replacement) {
      return replacement;
    }
    // Check if we have a single-char replacement.
    replacement = goog.i18n.diacritics.REPLACEMENTS_[charCode - MIN];
    goog.asserts.assert(replacement != '*', 'Missed multi-char replacement');
    return replacement == '^' ? null : replacement;
  };
  
  
  /**
   * Replaces things like Œ -> AE and ö -> o so people typing on american
   * keyboards can find people with special characters in their name.
   * This function currently only covers code points U+00C0 to U+017E.
   * @param {string} str The string to replace the characters for.
   * @return {string} The original string if no diacritics were found, otherwise
   *     a string with the diacritics replaced.
   */
  goog.i18n.diacritics.normalize = function(str) {
    var newStrParts = [];
    var start = 0;
    // We are optimizing for the case where there are no diacritics. We only do
    // string manipulations/construction in the case we find replacement chars
    // since JS doesn't allow for in-place manipulation of strings.
    for (var i = 0; i < str.length; i++) {
      var replacement = goog.i18n.diacritics.lookupReplacement_(
          str.charCodeAt(i));
      if (replacement) {
        if (start != i) {
          newStrParts.push(str.substr(start, i - start));
        }
        start = i + 1;
        newStrParts.push(replacement);
      }
    }
    if (newStrParts.length > 0) {
      newStrParts.push(str.substr(start));
      return newStrParts.join('');
    }
    return str;
  };
  