Пример #1
0
/**
 * New sprintf implementation for PHP.
 *
 * Modifiers:
 *
 *  " "   pad integers with spaces
 *  "-"   left adjusted field
 *   n    field size
 *  "."n  precision (floats only)
 *  "+"   Always place a sign (+ or -) in front of a number
 *
 * Type specifiers:
 *
 *  "%"   literal "%", modifiers are ignored.
 *  "b"   integer argument is printed as binary
 *  "c"   integer argument is printed as a single character
 *  "d"   argument is an integer
 *  "f"   the argument is a float
 *  "o"   integer argument is printed as octal
 *  "s"   argument is a string
 *  "x"   integer argument is printed as lowercase hexadecimal
 *  "X"   integer argument is printed as uppercase hexadecimal
 */
char *string_printf(const char *format, int len, CArrRef args, int *outlen) {
  Array vargs = args;
  if (!vargs.isNull() && !vargs->isVectorData()) {
    vargs = Array::Create();
    for (ArrayIter iter(args); iter; ++iter) {
      vargs.append(iter.second());
    }
  }

  if (len == 0) {
    return strdup("");
  }

  int size = 240;
  char *result = (char *)malloc(size);
  int outpos = 0;

  int argnum = 0, currarg = 1;
  for (int inpos = 0; inpos < len; ++inpos) {
    char ch = format[inpos];

    int expprec = 0;
    if (ch != '%') {
      appendchar(&result, &outpos, &size, ch);
      continue;
    }

    if (format[inpos + 1] == '%') {
      appendchar(&result, &outpos, &size, '%');
      inpos++;
      continue;
    }

    /* starting a new format specifier, reset variables */
    int alignment = ALIGN_RIGHT;
    int adjusting = 0;
    char padding = ' ';
    int always_sign = 0;
    int width, precision;
    inpos++;      /* skip the '%' */
    ch = format[inpos];

    if (isascii(ch) && !isalpha(ch)) {
      /* first look for argnum */
      int temppos = inpos;
      while (isdigit((int)format[temppos])) temppos++;
      if (format[temppos] == '$') {
        argnum = getnumber(format, &inpos);
        if (argnum <= 0) {
          free(result);
          throw_invalid_argument("argnum: must be greater than zero");
          return nullptr;
        }
        inpos++;  /* skip the '$' */
      } else {
        argnum = currarg++;
      }

      /* after argnum comes modifiers */
      for (;; inpos++) {
        ch = format[inpos];

        if (ch == ' ' || ch == '0') {
          padding = ch;
        } else if (ch == '-') {
          alignment = ALIGN_LEFT;
          /* space padding, the default */
        } else if (ch == '+') {
          always_sign = 1;
        } else if (ch == '\'') {
          padding = format[++inpos];
        } else {
          break;
        }
      }
      ch = format[inpos];

      /* after modifiers comes width */
      if (isdigit(ch)) {
        if ((width = getnumber(format, &inpos)) < 0) {
          free(result);
          throw_invalid_argument("width: must be greater than zero "
                                 "and less than %d", INT_MAX);
          return nullptr;
        }
        adjusting |= ADJ_WIDTH;
      } else {
        width = 0;
      }
      ch = format[inpos];

      /* after width and argnum comes precision */
      if (ch == '.') {
        ch = format[++inpos];
        if (isdigit((int)ch)) {
          if ((precision = getnumber(format, &inpos)) < 0) {
            free(result);
            throw_invalid_argument("precision: must be greater than zero "
                                   "and less than %d", INT_MAX);
            return nullptr;
          }
          ch = format[inpos];
          adjusting |= ADJ_PRECISION;
          expprec = 1;
        } else {
          precision = 0;
        }
      } else {
        precision = 0;
      }
    } else {
      width = precision = 0;
      argnum = currarg++;
    }

    if (argnum > vargs.size()) {
      free(result);
      throw_invalid_argument("arguments: (too few)");
      return nullptr;
    }

    if (ch == 'l') {
      ch = format[++inpos];
    }
    /* now we expect to find a type specifier */
    Variant tmp = vargs[argnum-1];

    switch (ch) {
    case 's': {
      String s = tmp.toString();
      appendstring(&result, &outpos, &size, s.c_str(),
                   width, precision, padding, alignment, s.size(),
                   0, expprec, 0);
      break;
    }
    case 'd':
      appendint(&result, &outpos, &size, tmp.toInt64(),
                width, padding, alignment, always_sign);
      break;
    case 'u':
      appenduint(&result, &outpos, &size, tmp.toInt64(),
                 width, padding, alignment);
      break;

    case 'g':
    case 'G':
    case 'e':
    case 'E':
    case 'f':
    case 'F':
      appenddouble(&result, &outpos, &size, tmp.toDouble(),
                   width, padding, alignment, precision, adjusting,
                   ch, always_sign);
      break;

    case 'c':
      appendchar(&result, &outpos, &size, tmp.toByte());
      break;

    case 'o':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 3, hexchars, expprec);
      break;

    case 'x':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 4, hexchars, expprec);
      break;

    case 'X':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 4, HEXCHARS, expprec);
      break;

    case 'b':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 1, hexchars, expprec);
      break;

    case '%':
      appendchar(&result, &outpos, &size, '%');

      break;
    default:
      break;
    }
  }

  /* possibly, we have to make sure we have room for the terminating null? */
  result[outpos]=0;
  if (outlen) *outlen = outpos;
  return result;
}
Пример #2
0
/*
 * Do format conversion placing the output in buffer
 */
static int xbuf_format_converter(char **outbuf, const char *fmt, va_list ap)
{
  register char *s = nullptr;
  char *q;
  int s_len;

  register int min_width = 0;
  int precision = 0;
  enum {
    LEFT, RIGHT
  } adjust;
  char pad_char;
  char prefix_char;

  double fp_num;
  wide_int i_num = (wide_int) 0;
  u_wide_int ui_num;

  char num_buf[NUM_BUF_SIZE];
  char char_buf[2];      /* for printing %% and %<unknown> */

#ifdef HAVE_LOCALE_H
  struct lconv *lconv = nullptr;
#endif

  /*
   * Flag variables
   */
  length_modifier_e modifier;
  boolean_e alternate_form;
  boolean_e print_sign;
  boolean_e print_blank;
  boolean_e adjust_precision;
  boolean_e adjust_width;
  int is_negative;

  int size = 240;
  char *result = (char *)malloc(size);
  int outpos = 0;

  while (*fmt) {
    if (*fmt != '%') {
      appendchar(&result, &outpos, &size, *fmt);
    } else {
      /*
       * Default variable settings
       */
      adjust = RIGHT;
      alternate_form = print_sign = print_blank = NO;
      pad_char = ' ';
      prefix_char = NUL;

      fmt++;

      /*
       * Try to avoid checking for flags, width or precision
       */
      if (isascii((int)*fmt) && !islower((int)*fmt)) {
        /*
         * Recognize flags: -, #, BLANK, +
         */
        for (;; fmt++) {
          if (*fmt == '-')
            adjust = LEFT;
          else if (*fmt == '+')
            print_sign = YES;
          else if (*fmt == '#')
            alternate_form = YES;
          else if (*fmt == ' ')
            print_blank = YES;
          else if (*fmt == '0')
            pad_char = '0';
          else
            break;
        }

        /*
         * Check if a width was specified
         */
        if (isdigit((int)*fmt)) {
          STR_TO_DEC(fmt, min_width);
          adjust_width = YES;
        } else if (*fmt == '*') {
          min_width = va_arg(ap, int);
          fmt++;
          adjust_width = YES;
          if (min_width < 0) {
            adjust = LEFT;
            min_width = -min_width;
          }
        } else
          adjust_width = NO;

        /*
         * Check if a precision was specified
         *
         * XXX: an unreasonable amount of precision may be specified
         * resulting in overflow of num_buf. Currently we
         * ignore this possibility.
         */
        if (*fmt == '.') {
          adjust_precision = YES;
          fmt++;
          if (isdigit((int)*fmt)) {
            STR_TO_DEC(fmt, precision);
          } else if (*fmt == '*') {
            precision = va_arg(ap, int);
            fmt++;
            if (precision < 0)
              precision = 0;
          } else
Пример #3
0
void handlepencilmsg(cJSON *json, struct user *usr) {
	struct pencil *p = &usr->pencil;
	struct buffer buf;
	char buffer_empty = 1;
	char mousedown;

	json = jsongetjson(json, "data");
	if (!json)
		return;
	json = json->child;

	p->ticksolid = max(p->ticksolid + 1, usr->gm->tick + SERVER_DELAY / TICK_LENGTH + usr->gm->inkdelay / TICK_LENGTH);

	/* this will be sent to other players */
	buf.start = 0;
	appendheader(&buf, MODE_PENCIL, usr->index);
	appendtick(&buf, p->ticksolid);

	if ((mousedown = json->valueint == -1))
		json = json->next;

	appendchar(&buf, mousedown);
	assert(!pthread_mutex_lock(&usr->gm->lock));

	while (json) {
		int x, y, tick;

		if (!readpencilmsg(&json, &x, &y, &tick))
			break;

		if (tick < p->tick || x < 0 || y < 0 || x > usr->gm->w || y > usr->gm->h)
			break;

		if (abs(usr->gm->tick + SERVER_DELAY / TICK_LENGTH - tick) > MAX_LAG_SPIKE / TICK_LENGTH) {
			warningplayer(usr, "error: tick of pencil msg not valid\n");
			break;
		}

		regenink(p, tick);

		if (mousedown) {
			if (p->ink < MOUSEDOWN_INK) {
				warningplayer(usr, "error: not enough ink for pencil down. %d required, %f left\n", MOUSEDOWN_INK, p->ink);
				break;
			}

			p->ink -= MOUSEDOWN_INK;
			p->down = 1;
			mousedown = 0;
		}
		else {
			double d = getlength(p->x - x, p->y - y);

			if (!p->down) {
				warningplayer(usr, "error: pencil move: pencil not down\n");
				break;
			}

			if (p->ink < d) {
				warningplayer(usr, "error: pencil move: not enough ink. %f required, %f left\n", d, p->ink);
				break;
			}

			if (d < INK_MIN_DISTANCE)
				p->down = 0;

			if (p->x == x && p->y == y)
				break;

			p->ink -= d;
			queuepencilseg(p, x, y);
		}

		appendpos(&buf, x, y);
		p->x = x;
		p->y = y;
		buffer_empty = 0;
	}

	if (!buffer_empty)
		airstr(buf.start, buf.at - buf.start, usr->gm, 0);

	pthread_mutex_unlock(&usr->gm->lock);
	free(buf.start);
}