Advertisement
S4T3K

SAMP format function

Jul 8th, 2014
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.18 KB | None | 0 0
  1.  
  2. // Taken, graciously, from AMXMODX
  3. //
  4.  
  5. #include "../main.h"
  6.  
  7. #include "format.h"
  8.  
  9. cell* get_amxaddr(AMX *amx,cell amx_addr);
  10.  
  11. #define ALT                     0x00000001              /* alternate form */
  12. #define HEXPREFIX       0x00000002              /* add 0x or 0X prefix */
  13. #define LADJUST         0x00000004              /* left adjustment */
  14. #define LONGDBL         0x00000008              /* long double */
  15. #define LONGINT         0x00000010              /* long integer */
  16. #define QUADINT         0x00000020              /* quad integer */
  17. #define SHORTINT        0x00000040              /* short integer */
  18. #define ZEROPAD         0x00000080              /* zero (as opposed to blank) pad */
  19. #define FPT                     0x00000100              /* floating point number */
  20. #define to_digit(c)             ((c) - '0')
  21. #define is_digit(c)             ((unsigned)to_digit(c) <= 9)
  22. #define to_char(n)              ((n) + '0')
  23. #define CHECK_ARGS(n) \
  24.         if ((arg+n) > args) { \
  25.                 LogError(amx, AMX_ERR_PARAMS, "String formatted incorrectly - parameter %d (total %d)", arg, args); \
  26.                 return 0; \
  27.         }
  28.  
  29. template <typename U>
  30. void AddString(U **buf_p, size_t &maxlen, const cell *string, int width, int prec)
  31. {
  32.         int             size = 0;
  33.         U               *buf;
  34.         static cell nlstr[] = {'(','n','u','l','l',')','\0'};
  35.  
  36.         buf = *buf_p;
  37.  
  38.         if (string == NULL)
  39.         {
  40.                 string = nlstr;
  41.                 prec = -1;
  42.         }
  43.  
  44.         if (prec >= 0)
  45.         {
  46.                 for (size = 0; size < prec; size++)
  47.                 {
  48.                         if (string[size] == '\0')
  49.                                 break;
  50.                 }
  51.         } else {
  52.                 while (string[size++]) ;
  53.                 size--;
  54.         }
  55.  
  56.         if (size > (int)maxlen)
  57.                 size = maxlen;
  58.  
  59.         maxlen -= size;
  60.         width -= size;
  61.  
  62.         while (size--)
  63.                 *buf++ = static_cast<U>(*string++);
  64.  
  65.         while (width-- > 0 && maxlen)
  66.         {
  67.                 *buf++ = ' ';
  68.                 maxlen--;
  69.         }
  70.  
  71.         *buf_p = buf;
  72. }
  73.  
  74. template <typename U>
  75. void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec)
  76. {
  77.         U               text[32];
  78.         int             digits;
  79.         double  signedVal;
  80.         U               *buf;
  81.         int             val;
  82.  
  83.         // get the sign
  84.         signedVal = fval;
  85.         if (fval < 0)
  86.                 fval = -fval;
  87.  
  88.         // write the float number
  89.         digits = 0;
  90.         val = (int)fval;
  91.         do {
  92.                 text[digits++] = '0' + val % 10;
  93.                 val /= 10;
  94.         } while (val);
  95.  
  96.         if (signedVal < 0)
  97.                 text[digits++] = '-';
  98.  
  99.         buf = *buf_p;
  100.  
  101.         while (digits < width && maxlen)
  102.         {
  103.                 *buf++ = ' ';
  104.                 width--;
  105.                 maxlen--;
  106.         }
  107.  
  108.         while (digits-- && maxlen)
  109.         {
  110.                 *buf++ = text[digits];
  111.                 maxlen--;
  112.         }
  113.  
  114.         *buf_p = buf;
  115.  
  116.         if (prec < 0)
  117.                 prec = 6;
  118.         // write the fraction
  119.         digits = 0;
  120.         while (digits < prec)
  121.         {
  122.                 fval -= (int) fval;
  123.                 fval *= 10.0;
  124.                 val = (int) fval;
  125.                 text[digits++] = '0' + val % 10;
  126.         }
  127.  
  128.         if (digits > 0 && maxlen)
  129.         {
  130.                 buf = *buf_p;
  131.                 *buf++ = '.';
  132.                 maxlen--;
  133.                 for (prec = 0; maxlen && prec < digits; prec++)
  134.                 {
  135.                         *buf++ = text[prec];
  136.                         maxlen--;
  137.                 }
  138.                 *buf_p = buf;
  139.         }
  140. }
  141.  
  142. template <typename U>
  143. void AddInt(U **buf_p, size_t &maxlen, int val, int width, int flags)
  144. {
  145.         U               text[32];
  146.         int             digits;
  147.         int             signedVal;
  148.         U               *buf;
  149.  
  150.         digits = 0;
  151.         signedVal = val;
  152.         if (val < 0)
  153.                 val = -val;
  154.         do {
  155.                 text[digits++] = '0' + val % 10;
  156.                 val /= 10;
  157.         } while (val);
  158.  
  159.         //if (signedVal < 0)
  160.                 //text[digits++] = '-';
  161.                
  162.         buf = *buf_p;
  163.  
  164.         if (signedVal < 0)
  165.         {
  166.                 if (flags & ZEROPAD)
  167.                 {
  168.                         *buf++ = '-';
  169.                 }
  170.                 else
  171.                 {
  172.                         text[digits++] = '-';
  173.                 }
  174.         }
  175.  
  176.         if( !(flags & LADJUST) )
  177.         {
  178.                 while (digits < width && maxlen)
  179.                 {
  180.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  181.                         width--;
  182.                         maxlen--;
  183.                 }
  184.         }
  185.  
  186.         while (digits-- && maxlen)
  187.         {
  188.                 *buf++ = text[digits];
  189.                 width--;
  190.                 maxlen--;
  191.         }
  192.  
  193.         if (flags & LADJUST)
  194.         {
  195.                 while (width-- && maxlen)
  196.                 {
  197.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  198.                         maxlen--;
  199.                 }
  200.         }
  201.  
  202.         *buf_p = buf;
  203. }
  204.  
  205. template <typename U>
  206. void AddHex(U **buf_p, size_t &maxlen, int val, int width, int flags)
  207. {
  208.         U               text[32];
  209.         int             digits;
  210.         //int           signedVal;
  211.         U               *buf;
  212.  
  213.         digits = 0;
  214.        
  215.         do
  216.         {
  217.                 text[digits] = '0' + val % 16;
  218.                 if (text[digits] > '9') text[digits] += 7; // Shift to letters
  219.                 digits++;
  220.                 val /= 16; // val >>= 4;
  221.         }
  222.         while (val);
  223.        
  224.         //text[digits++] = 'x';
  225.         //text[digits++] = '0';
  226.  
  227.         buf = *buf_p;
  228.        
  229.         if(!(flags & LADJUST))
  230.         {
  231.                 while (digits < width && maxlen)
  232.                 {
  233.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  234.                         width--;
  235.                         maxlen--;
  236.                 }
  237.         }
  238.  
  239.         while (digits-- && maxlen)
  240.         {
  241.                 *buf++ = text[digits];
  242.                 width--;
  243.                 maxlen--;
  244.         }
  245.  
  246.         if (flags & LADJUST)
  247.         {
  248.                 while (width-- && maxlen)
  249.                 {
  250.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  251.                         maxlen--;
  252.                 }
  253.         }
  254.  
  255.         *buf_p = buf;
  256. }
  257.  
  258. template <typename U>
  259. void AddBin(U **buf_p, size_t &maxlen, int val, int width, int flags)
  260. {
  261.         U               text[32];
  262.         int             digits;
  263.         //int           signedVal;
  264.         U               *buf;
  265.  
  266.         digits = 0;
  267.        
  268.         do
  269.         {
  270.                 text[digits++] = '0' + (val & 1);
  271.                 val >>= 1; // val >>= 4;
  272.         }
  273.         while (val);
  274.        
  275.         //text[digits++] = 'x';
  276.         //text[digits++] = '0';
  277.  
  278.         buf = *buf_p;
  279.                
  280.         if(!(flags & LADJUST))
  281.         {
  282.                 while (digits < width && maxlen)
  283.                 {
  284.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  285.                         width--;
  286.                         maxlen--;
  287.                 }
  288.         }
  289.  
  290.         while (digits-- && maxlen)
  291.         {
  292.                 *buf++ = text[digits];
  293.                 width--;
  294.                 maxlen--;
  295.         }
  296.  
  297.         if (flags & LADJUST)
  298.         {
  299.                 while (width-- && maxlen)
  300.                 {
  301.                         *buf++ = (flags & ZEROPAD) ? '0' : ' ';
  302.                         maxlen--;
  303.                 }
  304.         }
  305.  
  306.         *buf_p = buf;
  307. }
  308.  
  309. template <typename D, typename S>
  310. size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param)
  311. {
  312.         int             arg;
  313.         int             args = params[0] / sizeof(cell);
  314.         D               *buf_p;
  315.         D               ch;
  316.         int             flags;
  317.         int             width;
  318.         int             prec;
  319.         int             n;
  320.         char    sign;
  321.         const S *fmt;
  322.         size_t  llen = maxlen;
  323.  
  324.         buf_p = buffer;
  325.         arg = *param;
  326.         fmt = format;
  327.  
  328.         while (true)
  329.         {
  330.                 // run through the format string until we hit a '%' or '\0'
  331.                 for (ch = static_cast<D>(*fmt);
  332.                         llen && ((ch = static_cast<D>(*fmt)) != '\0' && ch != '%');
  333.                         fmt++)
  334.                 {
  335.                         *buf_p++ = static_cast<D>(ch);
  336.                         llen--;
  337.                 }
  338.                 if (ch == '\0' || llen <= 0)
  339.                         goto done;
  340.  
  341.                 // skip over the '%'
  342.                 fmt++;
  343.  
  344.                 // reset formatting state
  345.                 flags = 0;
  346.                 width = 0;
  347.                 prec = -1;
  348.                 sign = '\0';
  349.  
  350. rflag:
  351.                 ch = static_cast<D>(*fmt++);
  352. reswitch:
  353.                 switch(ch)
  354.                 {
  355.                 case '-':
  356.                         flags |= LADJUST;
  357.                         goto rflag;
  358.                 case '.':
  359.                         if (( ch = static_cast<D>(*fmt)) == '*')
  360.                         {
  361.                                 prec = *get_amxaddr(amx, params[arg++]);
  362.                                 fmt++;
  363.                                 goto rflag;
  364.                         }
  365.                         else
  366.                         {
  367.                                 n = 0;
  368.                                 while( is_digit( ( ch = static_cast<D>(*fmt++)) ) )
  369.                                         n = 10 * n + ( ch - '0' );
  370.                                 prec = n < 0 ? -1 : n;
  371.                                 goto reswitch;
  372.                         }
  373.                 case '0':
  374.                         flags |= ZEROPAD;
  375.                         goto rflag;
  376.                 case '1':
  377.                 case '2':
  378.                 case '3':
  379.                 case '4':
  380.                 case '5':
  381.                 case '6':
  382.                 case '7':
  383.                 case '8':
  384.                 case '9':
  385.                         n = 0;
  386.                         do {
  387.                                 n = 10 * n + ( ch - '0' );
  388.                                 ch = static_cast<D>(*fmt++);
  389.                         } while( is_digit( ch ) );
  390.                         width = n;
  391.                         goto reswitch;
  392.                 case '*':
  393.                         width = *get_amxaddr(amx, params[arg++]);
  394.                         goto rflag;
  395.                 case 'b':
  396.                         AddBin(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
  397.                         arg++;                  
  398.                         break;
  399.                 case 'c':
  400.                         *buf_p++ = static_cast<D>(*get_amxaddr(amx, params[arg]));
  401.                         arg++;
  402.                         break;
  403.                 case 'd':
  404.                 case 'i':
  405.                         AddInt(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
  406.                         arg++;
  407.                         break;
  408.                 case 'f':
  409.                         AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec);
  410.                         arg++;
  411.                         break;
  412.                 case 's':
  413.                         AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec);
  414.                         arg++;
  415.                         break;
  416.                 case 'h':
  417.                 case 'x':
  418.                         AddHex(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
  419.                         arg++;
  420.                         break;
  421.                 case '%':
  422.                         *buf_p++ = static_cast<D>(ch);
  423.                         if (!llen)
  424.                                 goto done;
  425.                         llen--;
  426.                         break;
  427.                 case '\0':
  428.                         *buf_p++ = static_cast<D>('%');
  429.                         if (!llen)
  430.                                 goto done;
  431.                         llen--;
  432.                         goto done;
  433.                         break;
  434.                 default:
  435.                         *buf_p++ = static_cast<D>(ch);
  436.                         if (!llen)
  437.                                 goto done;
  438.                         llen--;
  439.                         break;
  440.                 }
  441.         }
  442.  
  443. done:
  444.         *buf_p = static_cast<D>(0);
  445.         *param = arg;
  446.         return maxlen-llen;
  447. }
  448.  
  449. /**
  450.  * HACKHACK: The compiler will generate code for each case we need.
  451.  * Don't remove this, otherwise files that use certain code generations
  452.  *  will have extern problems.  For each case you need, add dummy code
  453.  *  here.
  454.  */
  455. void __format_prevent_removal()
  456. {
  457.         //acsprintf
  458.         atcprintf((cell *)NULL, 0, (const char *)NULL, NULL, NULL, NULL);
  459.         //accprintf
  460.         atcprintf((cell *)NULL, 0, (cell *)NULL, NULL, NULL, NULL);
  461.         //ascprintf
  462.         atcprintf((char *)NULL, 0, (cell *)NULL, NULL, NULL, NULL);
  463. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement