PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/base/zend-pack.cpp

http://github.com/facebook/hiphop-php
C++ | 967 lines | 772 code | 145 blank | 50 comment | 187 complexity | c57e556ed7acdfd87e7c473439161dfb MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 2.00 of the Zend license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.zend.com/license/2_00.txt. |
  12. | If you did not receive a copy of the Zend license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@zend.com so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include "hphp/runtime/base/zend-pack.h"
  18. #include "hphp/runtime/base/builtin-functions.h"
  19. #include "hphp/runtime/base/req-tiny-vector.h"
  20. #include <algorithm>
  21. namespace HPHP {
  22. #define INC_OUTPUTPOS(a,b) \
  23. if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
  24. raise_invalid_argument_warning \
  25. ("Type %c: integer overflow in format string", code); \
  26. return false; \
  27. } \
  28. outputpos += (a)*(b);
  29. ///////////////////////////////////////////////////////////////////////////////
  30. ZendPack::ZendPack() {
  31. int machine_endian_check = 1;
  32. int64_t i;
  33. machine_little_endian = ((char *)&machine_endian_check)[0];
  34. if (machine_little_endian) {
  35. /* Where to get lo to hi bytes from */
  36. byte_map[0] = 0;
  37. for (i = 0; i < (int)sizeof(int); i++) {
  38. int_map[i] = i;
  39. }
  40. machine_endian_short_map[0] = 0;
  41. machine_endian_short_map[1] = 1;
  42. big_endian_short_map[0] = 1;
  43. big_endian_short_map[1] = 0;
  44. little_endian_short_map[0] = 0;
  45. little_endian_short_map[1] = 1;
  46. machine_endian_int32_map[0] = 0;
  47. machine_endian_int32_map[1] = 1;
  48. machine_endian_int32_map[2] = 2;
  49. machine_endian_int32_map[3] = 3;
  50. big_endian_int32_map[0] = 3;
  51. big_endian_int32_map[1] = 2;
  52. big_endian_int32_map[2] = 1;
  53. big_endian_int32_map[3] = 0;
  54. little_endian_int32_map[0] = 0;
  55. little_endian_int32_map[1] = 1;
  56. little_endian_int32_map[2] = 2;
  57. little_endian_int32_map[3] = 3;
  58. machine_endian_int64_map[0] = 0;
  59. machine_endian_int64_map[1] = 1;
  60. machine_endian_int64_map[2] = 2;
  61. machine_endian_int64_map[3] = 3;
  62. machine_endian_int64_map[4] = 4;
  63. machine_endian_int64_map[5] = 5;
  64. machine_endian_int64_map[6] = 6;
  65. machine_endian_int64_map[7] = 7;
  66. big_endian_int64_map[0] = 7;
  67. big_endian_int64_map[1] = 6;
  68. big_endian_int64_map[2] = 5;
  69. big_endian_int64_map[3] = 4;
  70. big_endian_int64_map[4] = 3;
  71. big_endian_int64_map[5] = 2;
  72. big_endian_int64_map[6] = 1;
  73. big_endian_int64_map[7] = 0;
  74. little_endian_int64_map[0] = 0;
  75. little_endian_int64_map[1] = 1;
  76. little_endian_int64_map[2] = 2;
  77. little_endian_int64_map[3] = 3;
  78. little_endian_int64_map[4] = 4;
  79. little_endian_int64_map[5] = 5;
  80. little_endian_int64_map[6] = 6;
  81. little_endian_int64_map[7] = 7;
  82. } else {
  83. int64_t size = sizeof(int64_t);
  84. /* Where to get hi to lo bytes from */
  85. byte_map[0] = size - 1;
  86. for (i = 0; i < (int)sizeof(int); i++) {
  87. int_map[i] = size - (sizeof(int64_t) - i);
  88. }
  89. machine_endian_short_map[0] = size - 2;
  90. machine_endian_short_map[1] = size - 1;
  91. big_endian_short_map[0] = size - 2;
  92. big_endian_short_map[1] = size - 1;
  93. little_endian_short_map[0] = size - 1;
  94. little_endian_short_map[1] = size - 2;
  95. machine_endian_int32_map[0] = size - 4;
  96. machine_endian_int32_map[1] = size - 3;
  97. machine_endian_int32_map[2] = size - 2;
  98. machine_endian_int32_map[3] = size - 1;
  99. big_endian_int32_map[0] = size - 4;
  100. big_endian_int32_map[1] = size - 3;
  101. big_endian_int32_map[2] = size - 2;
  102. big_endian_int32_map[3] = size - 1;
  103. little_endian_int32_map[0] = size - 1;
  104. little_endian_int32_map[1] = size - 2;
  105. little_endian_int32_map[2] = size - 3;
  106. little_endian_int32_map[3] = size - 4;
  107. machine_endian_int64_map[0] = size - 8;
  108. machine_endian_int64_map[1] = size - 7;
  109. machine_endian_int64_map[2] = size - 6;
  110. machine_endian_int64_map[3] = size - 5;
  111. machine_endian_int64_map[4] = size - 4;
  112. machine_endian_int64_map[5] = size - 3;
  113. machine_endian_int64_map[6] = size - 2;
  114. machine_endian_int64_map[7] = size - 1;
  115. big_endian_int64_map[0] = size - 8;
  116. big_endian_int64_map[1] = size - 7;
  117. big_endian_int64_map[2] = size - 6;
  118. big_endian_int64_map[3] = size - 5;
  119. big_endian_int64_map[4] = size - 4;
  120. big_endian_int64_map[5] = size - 3;
  121. big_endian_int64_map[6] = size - 2;
  122. big_endian_int64_map[7] = size - 1;
  123. little_endian_int64_map[0] = size - 1;
  124. little_endian_int64_map[1] = size - 2;
  125. little_endian_int64_map[2] = size - 3;
  126. little_endian_int64_map[3] = size - 4;
  127. little_endian_int64_map[4] = size - 5;
  128. little_endian_int64_map[5] = size - 6;
  129. little_endian_int64_map[6] = size - 7;
  130. little_endian_int64_map[7] = size - 8;
  131. }
  132. }
  133. void ZendPack::pack(const Variant& val, int64_t size, int64_t *map,
  134. char *output) {
  135. int64_t n = val.toInt64();
  136. char *v = (char*)&n;
  137. for (int64_t i = 0; i < size; i++) {
  138. *output++ = v[map[i]];
  139. }
  140. }
  141. Variant ZendPack::pack(const String& fmt, const Array& argv) {
  142. /* Preprocess format into formatcodes and formatargs */
  143. req::TinyVector<char, 64> formatcodes; // up to 64 codes on the stack
  144. req::TinyVector<int, 64> formatargs;
  145. int argc = argv.size();
  146. const char *format = fmt.c_str();
  147. int formatlen = fmt.size();
  148. int currentarg = 0;
  149. for (int i = 0; i < formatlen; ) {
  150. char code = format[i++];
  151. int arg = 1;
  152. /* Handle format arguments if any */
  153. if (i < formatlen) {
  154. char c = format[i];
  155. if (c == '*') {
  156. arg = -1;
  157. i++;
  158. }
  159. else if (c >= '0' && c <= '9') {
  160. arg = atoi(&format[i]);
  161. while (format[i] >= '0' && format[i] <= '9' && i < formatlen) {
  162. i++;
  163. }
  164. }
  165. }
  166. /* Handle special arg '*' for all codes and check argv overflows */
  167. switch ((int) code) {
  168. /* Never uses any args */
  169. case 'x':
  170. case 'X':
  171. case '@':
  172. if (arg < 0) {
  173. raise_invalid_argument_warning("Type %c: '*' ignored", code);
  174. arg = 1;
  175. }
  176. break;
  177. /* Always uses one arg */
  178. case 'a':
  179. case 'A':
  180. case 'h':
  181. case 'H':
  182. case 'Z':
  183. if (currentarg >= argc) {
  184. raise_invalid_argument_warning("Type %c: not enough arguments", code);
  185. return false;
  186. }
  187. if (arg < 0) {
  188. arg = argv[currentarg].toString().size();
  189. //add one, because Z is always NUL-terminated
  190. if (code == 'Z') {
  191. arg++;
  192. }
  193. }
  194. currentarg++;
  195. break;
  196. /* Use as many args as specified */
  197. case 'q':
  198. case 'Q':
  199. case 'J':
  200. case 'P':
  201. case 'c':
  202. case 'C':
  203. case 's':
  204. case 'S':
  205. case 'i':
  206. case 'I':
  207. case 'l':
  208. case 'L':
  209. case 'n':
  210. case 'N':
  211. case 'v':
  212. case 'V':
  213. case 'f':
  214. case 'd':
  215. if (arg < 0) {
  216. arg = argc - currentarg;
  217. }
  218. currentarg += arg;
  219. if (currentarg > argc) {
  220. raise_invalid_argument_warning("Type %c: too few arguments", code);
  221. return false;
  222. }
  223. break;
  224. default:
  225. raise_invalid_argument_warning("Type %c: unknown format code", code);
  226. return false;
  227. }
  228. formatcodes.push_back(code);
  229. formatargs.push_back(arg);
  230. }
  231. if (currentarg < argc) {
  232. raise_invalid_argument_warning("%d arguments unused", (argc - currentarg));
  233. }
  234. int outputpos = 0, outputsize = 0;
  235. /* Calculate output length and upper bound while processing*/
  236. for (int i = 0; i < (int)formatcodes.size(); i++) {
  237. int code = (int) formatcodes[i];
  238. int arg = formatargs[i];
  239. switch ((int) code) {
  240. case 'h':
  241. case 'H':
  242. INC_OUTPUTPOS((arg + (arg % 2)) / 2,1); /* 4 bit per arg */
  243. break;
  244. case 'a':
  245. case 'A':
  246. case 'c':
  247. case 'C':
  248. case 'x':
  249. case 'Z':
  250. INC_OUTPUTPOS(arg,1); /* 8 bit per arg */
  251. break;
  252. case 's':
  253. case 'S':
  254. case 'n':
  255. case 'v':
  256. INC_OUTPUTPOS(arg,2); /* 16 bit per arg */
  257. break;
  258. case 'i':
  259. case 'I':
  260. INC_OUTPUTPOS(arg,sizeof(int));
  261. break;
  262. case 'l':
  263. case 'L':
  264. case 'N':
  265. case 'V':
  266. INC_OUTPUTPOS(arg,4); /* 32 bit per arg */
  267. break;
  268. case 'q':
  269. case 'Q':
  270. case 'J':
  271. case 'P':
  272. INC_OUTPUTPOS(arg,8); /* 64 bit per arg */
  273. break;
  274. case 'f':
  275. INC_OUTPUTPOS(arg,sizeof(float));
  276. break;
  277. case 'd':
  278. INC_OUTPUTPOS(arg,sizeof(double));
  279. break;
  280. case 'X':
  281. outputpos -= arg;
  282. if (outputpos < 0) {
  283. raise_invalid_argument_warning("Type %c: outside of string", code);
  284. outputpos = 0;
  285. }
  286. break;
  287. case '@':
  288. outputpos = arg;
  289. break;
  290. }
  291. if (outputsize < outputpos) {
  292. outputsize = outputpos;
  293. }
  294. }
  295. String str = String(outputsize, ReserveString);
  296. char *output = str.mutableData();
  297. outputpos = 0;
  298. currentarg = 0;
  299. /* Do actual packing */
  300. for (int i = 0; i < (int)formatcodes.size(); i++) {
  301. int code = (int) formatcodes[i];
  302. int arg = formatargs[i];
  303. String val;
  304. const char *s;
  305. int slen;
  306. switch ((int) code) {
  307. case 'a':
  308. case 'A':
  309. case 'Z': {
  310. int arg_cp = (code != 'Z') ? arg : std::max(0, arg - 1);
  311. memset(&output[outputpos], (code != 'A') ? '\0' : ' ', arg);
  312. val = argv[currentarg++].toString();
  313. s = val.c_str();
  314. slen = val.size();
  315. memcpy(&output[outputpos], s, (slen < arg_cp) ? slen : arg_cp);
  316. outputpos += arg;
  317. }
  318. break;
  319. case 'h':
  320. case 'H': {
  321. int nibbleshift = (code == 'h') ? 0 : 4;
  322. int first = 1;
  323. const char *v;
  324. val = argv[currentarg++].toString();
  325. v = val.data();
  326. slen = val.size();
  327. outputpos--;
  328. if (arg > slen) {
  329. raise_invalid_argument_warning
  330. ("Type %c: not enough characters in string", code);
  331. arg = slen;
  332. }
  333. while (arg-- > 0) {
  334. char n = *v++;
  335. if (n >= '0' && n <= '9') {
  336. n -= '0';
  337. } else if (n >= 'A' && n <= 'F') {
  338. n -= ('A' - 10);
  339. } else if (n >= 'a' && n <= 'f') {
  340. n -= ('a' - 10);
  341. } else {
  342. raise_invalid_argument_warning("Type %c: illegal hex digit %c", code, n);
  343. n = 0;
  344. }
  345. if (first--) {
  346. output[++outputpos] = 0;
  347. } else {
  348. first = 1;
  349. }
  350. output[outputpos] |= (n << nibbleshift);
  351. nibbleshift = (nibbleshift + 4) & 7;
  352. }
  353. outputpos++;
  354. break;
  355. }
  356. case 'c':
  357. case 'C':
  358. while (arg-- > 0) {
  359. pack(argv[currentarg++], 1, byte_map, &output[outputpos]);
  360. outputpos++;
  361. }
  362. break;
  363. case 's':
  364. case 'S':
  365. case 'n':
  366. case 'v': {
  367. int64_t *map = machine_endian_short_map;
  368. if (code == 'n') {
  369. map = big_endian_short_map;
  370. } else if (code == 'v') {
  371. map = little_endian_short_map;
  372. }
  373. while (arg-- > 0) {
  374. pack(argv[currentarg++], 2, map, &output[outputpos]);
  375. outputpos += 2;
  376. }
  377. break;
  378. }
  379. case 'i':
  380. case 'I':
  381. while (arg-- > 0) {
  382. pack(argv[currentarg++], sizeof(int), int_map, &output[outputpos]);
  383. outputpos += sizeof(int);
  384. }
  385. break;
  386. case 'l':
  387. case 'L':
  388. case 'N':
  389. case 'V': {
  390. int64_t *map = machine_endian_int32_map;
  391. if (code == 'N') {
  392. map = big_endian_int32_map;
  393. } else if (code == 'V') {
  394. map = little_endian_int32_map;
  395. }
  396. while (arg-- > 0) {
  397. pack(argv[currentarg++], 4, map, &output[outputpos]);
  398. outputpos += 4;
  399. }
  400. break;
  401. }
  402. case 'q':
  403. case 'Q':
  404. case 'J':
  405. case 'P': {
  406. int64_t *map = machine_endian_int64_map;
  407. if (code == 'J') {
  408. map = big_endian_int64_map;
  409. } else if (code == 'P') {
  410. map = little_endian_int64_map;
  411. }
  412. while (arg-- > 0) {
  413. pack(argv[currentarg++], 8, map, &output[outputpos]);
  414. outputpos += 8;
  415. }
  416. break;
  417. }
  418. case 'f': {
  419. float v;
  420. while (arg-- > 0) {
  421. v = argv[currentarg++].toDouble();
  422. memcpy(&output[outputpos], &v, sizeof(v));
  423. outputpos += sizeof(v);
  424. }
  425. break;
  426. }
  427. case 'd': {
  428. double v;
  429. while (arg-- > 0) {
  430. v = argv[currentarg++].toDouble();
  431. memcpy(&output[outputpos], &v, sizeof(v));
  432. outputpos += sizeof(v);
  433. }
  434. break;
  435. }
  436. case 'x':
  437. memset(&output[outputpos], '\0', arg);
  438. outputpos += arg;
  439. break;
  440. case 'X':
  441. outputpos -= arg;
  442. if (outputpos < 0) {
  443. outputpos = 0;
  444. }
  445. break;
  446. case '@':
  447. if (arg > outputpos) {
  448. memset(&output[outputpos], '\0', arg - outputpos);
  449. }
  450. outputpos = arg;
  451. break;
  452. }
  453. }
  454. str.setSize(outputpos);
  455. return str;
  456. }
  457. int64_t ZendPack::unpack(const char *data, int64_t size, int issigned,
  458. int64_t *map) {
  459. int64_t result;
  460. char *cresult = (char *) &result;
  461. int i;
  462. result = issigned ? -1 : 0;
  463. for (i = 0; i < size; i++) {
  464. cresult[map[i]] = *data++;
  465. }
  466. return result;
  467. }
  468. Variant ZendPack::unpack(const String& fmt, const String& data) {
  469. const char *format = fmt.c_str();
  470. int formatlen = fmt.size();
  471. const char *input = data.c_str();
  472. int inputlen = data.size();
  473. int inputpos = 0;
  474. Array ret = Array::Create();
  475. while (formatlen-- > 0) {
  476. char type = *(format++);
  477. int arg = 1, argb;
  478. const char *name;
  479. int namelen;
  480. int size=0;
  481. /* Handle format arguments if any */
  482. if (formatlen > 0) {
  483. char c = *format;
  484. if (c >= '0' && c <= '9') {
  485. arg = atoi(format);
  486. while (formatlen > 0 && *format >= '0' && *format <= '9') {
  487. format++;
  488. formatlen--;
  489. }
  490. } else if (c == '*') {
  491. arg = -1;
  492. format++;
  493. formatlen--;
  494. }
  495. }
  496. /* Get of new value in array */
  497. name = format;
  498. argb = arg;
  499. while (formatlen > 0 && *format != '/') {
  500. formatlen--;
  501. format++;
  502. }
  503. namelen = format - name;
  504. if (namelen > 200)
  505. namelen = 200;
  506. switch ((int) type) {
  507. /* Never use any input */
  508. case 'X':
  509. size = -1;
  510. if (arg < 0) {
  511. raise_invalid_argument_warning("Type %c: '*' ignored", type);
  512. arg = 1;
  513. }
  514. break;
  515. case '@':
  516. size = 0;
  517. break;
  518. case 'a':
  519. case 'A':
  520. case 'Z':
  521. size = arg;
  522. arg = 1;
  523. break;
  524. case 'h':
  525. case 'H':
  526. size = (arg > 0) ? (arg + (arg % 2)) / 2 : arg;
  527. arg = 1;
  528. break;
  529. /* Use 1 byte of input */
  530. case 'c':
  531. case 'C':
  532. case 'x':
  533. size = 1;
  534. break;
  535. /* Use 2 bytes of input */
  536. case 's':
  537. case 'S':
  538. case 'n':
  539. case 'v':
  540. size = 2;
  541. break;
  542. /* Use machine dependent bytes of input */
  543. case 'i':
  544. case 'I':
  545. size = sizeof(int);
  546. break;
  547. /* Use 4 bytes of input */
  548. case 'l':
  549. case 'L':
  550. case 'N':
  551. case 'V':
  552. size = 4;
  553. break;
  554. /* Use 8 bytes of input */
  555. case 'q':
  556. case 'Q':
  557. case 'J':
  558. case 'P':
  559. size = 8;
  560. break;
  561. /* Use sizeof(float) bytes of input */
  562. case 'f':
  563. size = sizeof(float);
  564. break;
  565. /* Use sizeof(double) bytes of input */
  566. case 'd':
  567. size = sizeof(double);
  568. break;
  569. default:
  570. raise_invalid_argument_warning("Invalid format type %c", type);
  571. return false;
  572. }
  573. /* Do actual unpacking */
  574. for (int i = 0; i != arg; i++ ) {
  575. /* Space for name + number, safe as namelen is ensured <= 200 */
  576. char n[256];
  577. if (arg != 1 || namelen == 0) {
  578. /* Need to add element number to name */
  579. snprintf(n, sizeof(n), "%.*s%d", namelen, name, i + 1);
  580. } else {
  581. /* Truncate name to next format code or end of string */
  582. snprintf(n, sizeof(n), "%.*s", namelen, name);
  583. }
  584. const auto n_str = String(n, CopyString);
  585. int64_t n_int;
  586. const auto n_key = n_str.get()->isStrictlyInteger(n_int)
  587. ? Variant(n_int)
  588. : Variant(n_str);
  589. if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {
  590. raise_invalid_argument_warning("Type %c: integer overflow", type);
  591. inputpos = 0;
  592. }
  593. if ((inputpos + size) <= inputlen) {
  594. switch ((int) type) {
  595. case 'a':
  596. case 'A':
  597. case 'Z': {
  598. int len = inputlen - inputpos; /* Remaining string */
  599. /* If size was given take minimum of len and size */
  600. if ((size >= 0) && (len > size)) {
  601. len = size;
  602. }
  603. size = len;
  604. /* A will strip any trailing whitespace */
  605. if (type == 'A')
  606. {
  607. char padn = '\0'; char pads = ' '; char padt = '\t';
  608. char padc = '\r'; char padl = '\n';
  609. while (--len >= 0) {
  610. if (input[inputpos + len] != padn
  611. && input[inputpos + len] != pads
  612. && input[inputpos + len] != padt
  613. && input[inputpos + len] != padc
  614. && input[inputpos + len] != padl
  615. )
  616. break;
  617. }
  618. }
  619. /* Remove everything after the first null */
  620. if (type=='Z') {
  621. int s;
  622. for (s=0 ; s < len ; s++) {
  623. if (input[inputpos + s] == '\0')
  624. break;
  625. }
  626. len = s;
  627. }
  628. /*only A is \0 terminated*/
  629. if (type=='A')
  630. len++;
  631. ret.set(n_key, String(input + inputpos, len, CopyString));
  632. break;
  633. }
  634. case 'h':
  635. case 'H': {
  636. int len = (inputlen - inputpos) * 2; /* Remaining */
  637. int nibbleshift = (type == 'h') ? 0 : 4;
  638. int first = 1;
  639. char *buf;
  640. int ipos, opos;
  641. /* If size was given take minimum of len and size */
  642. if (size >= 0 && len > (size * 2)) {
  643. len = size * 2;
  644. }
  645. if (argb > 0) {
  646. len -= argb % 2;
  647. }
  648. String s = String(len, ReserveString);
  649. buf = s.mutableData();
  650. for (ipos = opos = 0; opos < len; opos++) {
  651. char c = (input[inputpos + ipos] >> nibbleshift) & 0xf;
  652. if (c < 10) {
  653. c += '0';
  654. } else {
  655. c += 'a' - 10;
  656. }
  657. buf[opos] = c;
  658. nibbleshift = (nibbleshift + 4) & 7;
  659. if (first-- == 0) {
  660. ipos++;
  661. first = 1;
  662. }
  663. }
  664. s.setSize(len);
  665. ret.set(n_key, s);
  666. break;
  667. }
  668. case 'c':
  669. case 'C': {
  670. int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0;
  671. ret.set(n_key, unpack(&input[inputpos], 1, issigned, byte_map));
  672. break;
  673. }
  674. case 's':
  675. case 'S':
  676. case 'n':
  677. case 'v': {
  678. int issigned = 0;
  679. int64_t *map = machine_endian_short_map;
  680. if (type == 's') {
  681. issigned = input[inputpos + (machine_little_endian ? 1 : 0)] &
  682. 0x80;
  683. } else if (type == 'n') {
  684. map = big_endian_short_map;
  685. } else if (type == 'v') {
  686. map = little_endian_short_map;
  687. }
  688. ret.set(n_key, unpack(&input[inputpos], 2, issigned, map));
  689. break;
  690. }
  691. case 'i':
  692. case 'I': {
  693. int32_t v = 0;
  694. int issigned = 0;
  695. if (type == 'i') {
  696. issigned = input[inputpos + (machine_little_endian ?
  697. (sizeof(int) - 1) : 0)] & 0x80;
  698. } else if (sizeof(int32_t) > 4 &&
  699. (input[inputpos + machine_endian_int32_map[3]]
  700. & 0x80) == 0x80) {
  701. v = ~INT_MAX;
  702. }
  703. v |= unpack(&input[inputpos], sizeof(int), issigned, int_map);
  704. if (type == 'i') {
  705. ret.set(n_key, v);
  706. } else {
  707. uint64_t u64 = uint32_t(v);
  708. ret.set(n_key, u64);
  709. }
  710. break;
  711. }
  712. case 'l':
  713. case 'L':
  714. case 'N':
  715. case 'V': {
  716. int issigned = 0;
  717. int64_t *map = machine_endian_int32_map;
  718. int64_t v = 0;
  719. if (type == 'l' || type == 'L') {
  720. issigned = input[inputpos + (machine_little_endian ? 3 : 0)]
  721. & 0x80;
  722. } else if (type == 'N') {
  723. issigned = input[inputpos] & 0x80;
  724. map = big_endian_int32_map;
  725. } else if (type == 'V') {
  726. issigned = input[inputpos + 3] & 0x80;
  727. map = little_endian_int32_map;
  728. }
  729. if (sizeof(int32_t) > 4 && issigned) {
  730. v = ~INT_MAX;
  731. }
  732. v |= unpack(&input[inputpos], 4, issigned, map);
  733. if (type == 'l') {
  734. ret.set(n_key, v);
  735. } else {
  736. uint64_t u64 = uint32_t(v);
  737. ret.set(n_key, u64);
  738. }
  739. break;
  740. }
  741. case 'q':
  742. case 'Q':
  743. case 'J':
  744. case 'P': {
  745. int issigned = 0;
  746. int64_t *map = machine_endian_int64_map;
  747. int64_t v = 0;
  748. if (type == 'q' || type == 'Q') {
  749. issigned = input[inputpos + (machine_little_endian ? 7 : 0)] & 0x80;
  750. } else if (type == 'J') {
  751. issigned = input[inputpos] & 0x80;
  752. map = big_endian_int64_map;
  753. } else if (type == 'P') {
  754. issigned = input[inputpos + 7] & 0x80;
  755. map = little_endian_int64_map;
  756. }
  757. v = unpack(&input[inputpos], 8, issigned, map);
  758. if (type == 'q') {
  759. ret.set(n_key, v);
  760. } else {
  761. uint64_t u64 = uint64_t(v);
  762. ret.set(n_key, u64);
  763. }
  764. break;
  765. }
  766. case 'f': {
  767. float v;
  768. memcpy(&v, &input[inputpos], sizeof(float));
  769. ret.set(n_key, (double)v);
  770. break;
  771. }
  772. case 'd': {
  773. double v;
  774. memcpy(&v, &input[inputpos], sizeof(double));
  775. ret.set(n_key, v);
  776. break;
  777. }
  778. case 'x':
  779. /* Do nothing with input, just skip it */
  780. break;
  781. case 'X':
  782. if (inputpos < size) {
  783. inputpos = -size;
  784. i = arg - 1; /* Break out of for loop */
  785. if (arg >= 0) {
  786. raise_invalid_argument_warning("Type %c: outside of string", type);
  787. }
  788. }
  789. break;
  790. case '@':
  791. if (arg <= inputlen) {
  792. inputpos = arg;
  793. } else {
  794. raise_invalid_argument_warning("Type %c: outside of string", type);
  795. }
  796. i = arg - 1; /* Done, break out of for loop */
  797. break;
  798. }
  799. inputpos += size;
  800. if (inputpos < 0) {
  801. if (size != -1) { /* only print warning if not working with * */
  802. raise_invalid_argument_warning("Type %c: outside of string", type);
  803. }
  804. inputpos = 0;
  805. }
  806. } else if (arg < 0) {
  807. /* Reached end of input for '*' repeater */
  808. break;
  809. } else {
  810. raise_invalid_argument_warning
  811. ("Type %c: not enough input, need %d, have %d",
  812. type, size, inputlen - inputpos);
  813. return false;
  814. }
  815. }
  816. formatlen--; /* Skip '/' separator, does no harm if inputlen == 0 */
  817. format++;
  818. }
  819. return ret;
  820. }
  821. ///////////////////////////////////////////////////////////////////////////////
  822. }