1/* 2 * jQuery sprintf - perl based functionallity for sprintf and friends. 3 * 4 * Copyright © 2008 Carl Fürstenberg 5 * 6 * Released under GPL, BSD, or MIT license. 7 * --------------------------------------------------------------------------- 8 * GPL: 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 3 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 * 23 * Copyright (c) The Regents of the University of California. 24 * All rights reserved. 25 * 26 * --------------------------------------------------------------------------- 27 * BSD: 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 °* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * --------------------------------------------------------------------------- 54 * MIT: 55 * 56 * Permission is hereby granted, free of charge, to any person obtaining a copy 57 * of this software and associated documentation files (the "Software"), to deal 58 * in the Software without restriction, including without limitation the rights 59 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 60 * copies of the Software, and to permit persons to whom the Software is 61 * furnished to do so, subject to the following conditions: 62 * 63 * The above copyright notice and this permission notice shall be included in 64 * all copies or substantial portions of the Software. 65 * 66 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 67 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 68 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 69 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 70 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 71 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 72 * THE SOFTWARE. 73 * 74 * --------------------------------------------------------------------------- 75 * 76 * Version: 0.0.6 77 */ 78 79/** 80 * Inserts the arguments into the format and returns the formated string 81 * 82 * @example alert($.vsprintf( "%s %s", [ "Hello", "world" ] )); 83 * 84 * @param String format the format to use 85 * @param Array args the arguments to insert into the format 86 * @return String the formated string 87 */ 88jQuery.vsprintf = function jQuery_vsprintf( format, args ) { 89 if( format == null ) { 90 throw "Not enough arguments for vsprintf"; 91 } 92 if( args == null ) { 93 args = []; 94 } 95 96 function _sprintf_format( type, value, flags ) { 97 98 // Similar to how perl printf works 99 if( value == undefined ) { 100 if( type == 's' ) { 101 return ''; 102 } else { 103 return '0'; 104 } 105 } 106 107 var result; 108 var prefix = ''; 109 var fill = ''; 110 var fillchar = ' '; 111 if( flags['short'] || flags['long'] || flags['long_long'] ) { 112 /* This is pretty ugly, but as JS ignores bit lengths except 113 * somewhat when working with bit operators. 114 * So we fake a bit :) */ 115 switch( type ) { 116 case 'e': 117 case 'f': 118 case 'G': 119 case 'E': 120 case 'G': 121 case 'd': /* signed */ 122 if( flags['short'] ) { 123 if( value >= 32767 ) { 124 value = 32767; 125 } else if( value <= -32767-1 ) { 126 value = -32767-1; 127 } 128 } else if ( flags['long'] ) { 129 if( value >= 2147483647 ) { 130 value = 2147483647; 131 } else if( value <= -2147483647-1 ) { 132 value = -2147483647-1; 133 } 134 } else /*if ( flags['long_long'] )*/ { 135 if( value >= 9223372036854775807 ) { 136 value = 9223372036854775807; 137 } else if( value <= -9223372036854775807-1 ) { 138 value = -9223372036854775807-1; 139 } 140 } 141 break; 142 case 'X': 143 case 'B': 144 case 'u': 145 case 'o': 146 case 'x': 147 case 'b': /* unsigned */ 148 if( value < 0 ) { 149 /* Pretty ugly, but one only solution */ 150 value = Math.abs( value ) - 1; 151 } 152 if( flags['short'] ) { 153 if( value >= 65535 ) { 154 value = 65535; 155 } 156 } else if ( flags['long'] ) { 157 if( value >= 4294967295 ) { 158 value = 4294967295; 159 } 160 161 } else /*if ( flags['long_long'] )*/ { 162 if( value >= 18446744073709551615 ) { 163 value = 18446744073709551615; 164 } 165 166 } 167 break; 168 } 169 } 170 switch( type ) { 171 case 'c': 172 result = String.fromCharCode( parseInt( value ) ); 173 break; 174 case 's': 175 result = value.toString(); 176 break; 177 case 'd': 178 result = (new Number( parseInt( value ) ) ).toString(); 179 break; 180 case 'u': 181 result = (new Number( parseInt( value ) ) ).toString(); 182 break; 183 case 'o': 184 result = (new Number( parseInt( value ) ) ).toString(8); 185 break; 186 case 'x': 187 result = (new Number( parseInt( value ) ) ).toString(16); 188 break; 189 case 'B': 190 case 'b': 191 result = (new Number( parseInt( value ) ) ).toString(2); 192 break; 193 case 'e': 194 var digits = flags['precision'] ? flags['precision'] : 6; 195 result = (new Number( value ) ).toExponential( digits ).toString(); 196 break; 197 case 'f': 198 var digits = flags['precision'] ? flags['precision'] : 6; 199 result = (new Number( value ) ).toFixed( digits ).toString(); 200 break; 201 case 'g': 202 var digits = flags['precision'] ? flags['precision'] : 6; 203 result = (new Number( value ) ).toPrecision( digits ).toString(); 204 break; 205 case 'X': 206 result = (new Number( parseInt( value ) ) ).toString(16).toUpperCase(); 207 break; 208 case 'E': 209 var digits = flags['precision'] ? flags['precision'] : 6; 210 result = (new Number( value ) ).toExponential( digits ).toString().toUpperCase(); 211 break; 212 case 'G': 213 var digits = flags['precision'] ? flags['precision'] : 6; 214 result = (new Number( value ) ).toPrecision( digits ).toString().toUpperCase(); 215 break; 216 } 217 218 if(flags['+'] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) { 219 prefix = '+'; 220 } 221 222 if(flags[' '] && parseFloat( value ) > 0 && ['d','e','f','g','E','G'].indexOf(type) != -1 ) { 223 prefix = ' '; 224 } 225 226 if( flags['#'] && parseInt( value ) != 0 ) { 227 switch(type) { 228 case 'o': 229 prefix = '0'; 230 break; 231 case 'x': 232 case 'X': 233 prefix = '0x'; 234 break; 235 case 'b': 236 prefix = '0b'; 237 break; 238 case 'B': 239 prefix = '0B'; 240 break; 241 } 242 } 243 244 if( flags['0'] && !flags['-'] ) { 245 fillchar = '0'; 246 } 247 248 if( flags['width'] && flags['width'] > ( result.length + prefix.length ) ) { 249 var tofill = flags['width'] - result.length - prefix.length; 250 for( var i = 0; i < tofill; ++i ) { 251 fill += fillchar; 252 } 253 } 254 255 if( flags['-'] && !flags['0'] ) { 256 result += fill; 257 } else { 258 result = fill + result; 259 } 260 261 return prefix + result; 262 }; 263 264 var result = ""; 265 266 var index = 0; 267 var current_index = 0; 268 var flags = { 269 'long': false, 270 'short': false, 271 'long_long': false 272 }; 273 var in_operator = false; 274 var relative = false; 275 var precision = false; 276 var fixed = false; 277 var vector = false; 278 var bitwidth = false; 279 var vector_delimiter = '.'; 280 281 for( var i = 0; i < format.length; ++i ) { 282 var current_char = format.charAt(i); 283 if( in_operator ) { 284 // backward compat 285 switch( current_char ) { 286 case 'i': 287 current_char = 'd'; 288 break; 289 case 'D': 290 flags['long'] = true; 291 current_char = 'd'; 292 break; 293 case 'U': 294 flags['long'] = true; 295 current_char = 'u'; 296 break; 297 case 'O': 298 flags['long'] = true; 299 current_char = 'o'; 300 break; 301 case 'F': 302 current_char = 'f'; 303 break; 304 } 305 switch( current_char ) { 306 case 'c': 307 case 's': 308 case 'd': 309 case 'u': 310 case 'o': 311 case 'x': 312 case 'e': 313 case 'f': 314 case 'g': 315 case 'X': 316 case 'E': 317 case 'G': 318 case 'b': 319 case 'B': 320 var value = args[current_index]; 321 if( vector ) { 322 var fixed_value = value; 323 if( value instanceof Array ) { 324 // if the value is an array, assume to work on it directly 325 fixed_value = value; 326 } else if ( typeof(value) == 'string' || value instanceof String ) { 327 // normal behavour, assume string is a bitmap 328 fixed_value = value.split('').map( function( value ) { return value.charCodeAt(); } ); 329 } else if ( ( typeof(value) == 'number' || value instanceof Number ) && flags['bitwidth'] ) { 330 // if we defined a width, assume we want to vectorize the bits directly 331 fixed_value = []; 332 do { 333 fixed_value.unshift( value & ~(~0 << flags['bitwidth'] ) ); 334 } while( value >>>= flags['bitwidth'] ); 335 } else { 336 fixed_value = value.toString().split('').map( function( value ) { return value.charCodeAt(); } ); 337 338 } 339 result += fixed_value.map( function( value ) { 340 return _sprintf_format( current_char, value, flags ); 341 }).join( vector_delimiter ); 342 } else { 343 result += _sprintf_format( current_char, value, flags ); 344 } 345 if( !fixed ) { 346 ++index; 347 } 348 current_index = index; 349 flags = {}; 350 relative = false; 351 in_operator = false; 352 precision = false; 353 fixed = false; 354 vector = false; 355 bitwidth = false; 356 vector_delimiter = '.'; 357 break; 358 case 'v': 359 vector = true; 360 break; 361 case ' ': 362 case '0': 363 case '-': 364 case '+': 365 case '#': 366 flags[current_char] = true; 367 break; 368 case '*': 369 relative = true; 370 break; 371 case '.': 372 precision = true; 373 break; 374 case '@': 375 bitwidth = true; 376 break; 377 case 'l': 378 if( flags['long'] ) { 379 flags['long_long'] = true; 380 flags['long'] = false; 381 } else { 382 flags['long'] = true; 383 flags['long_long'] = false; 384 } 385 flags['short'] = false; 386 break; 387 case 'q': 388 case 'L': 389 flags['long_long'] = true; 390 flags['long'] = false; 391 flags['short'] = false; 392 break; 393 case 'h': 394 flags['short'] = true; 395 flags['long'] = false; 396 flags['long_long'] = false; 397 break; 398 } 399 if( /\d/.test( current_char ) ) { 400 var num = parseInt( format.substr( i ) ); 401 var len = num.toString().length; 402 i += len - 1; 403 var next = format.charAt( i + 1 ); 404 if( next == '$' ) { 405 if( num < 0 || num > args.length ) { 406 throw "out of bound"; 407 } 408 if( relative ) { 409 if( precision ) { 410 flags['precision'] = args[num - 1]; 411 precision = false; 412 } else if( format.charAt( i + 2 ) == 'v' ) { 413 vector_delimiter = args[num - 1]; 414 }else { 415 flags['width'] = args[num - 1]; 416 } 417 relative = false; 418 } else { 419 fixed = true; 420 current_index = num - 1; 421 } 422 ++i; 423 } else if( precision ) { 424 flags['precision'] = num; 425 precision = false; 426 } else if( bitwidth ) { 427 flags['bitwidth'] = num; 428 bitwidth = false; 429 } else { 430 flags['width'] = num; 431 } 432 } else if ( relative && !/\d/.test( format.charAt( i + 1 ) ) ) { 433 if( precision ) { 434 flags['precision'] = args[current_index]; 435 precision = false; 436 } else if( format.charAt( i + 1 ) == 'v' ) { 437 vector_delimiter = args[current_index]; 438 } else { 439 flags['width'] = args[current_index]; 440 } 441 ++index; 442 if( !fixed ) { 443 current_index++; 444 } 445 relative = false; 446 } 447 } else { 448 if( current_char == '%' ) { 449 // If the next character is an %, then we have an escaped %, 450 // we'll take this as an exception to the normal lookup, as 451 // we don't want/need to process this. 452 if( format.charAt(i+1) == '%' ) { 453 result += '%'; 454 ++i; 455 continue; 456 } 457 in_operator = true; 458 continue; 459 } else { 460 result += current_char; 461 continue; 462 } 463 } 464 } 465 return result; 466};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.