| 122 | } |
| 123 | |
| 124 | void WriteF(const char* __restrict format, va_list args){ |
| 125 | |
| 126 | while (*format != '\0') { |
| 127 | if (format[0] != '%' || format[1] == '%') { |
| 128 | if (format[0] == '%') |
| 129 | format++; |
| 130 | size_t amount = 1; |
| 131 | while (format[amount] && format[amount] != '%') |
| 132 | amount++; |
| 133 | WriteN(format, amount); |
| 134 | format += amount; |
| 135 | continue; |
| 136 | } |
| 137 | |
| 138 | const char* format_begun_at = format++; |
| 139 | |
| 140 | bool hex = true; |
| 141 | switch(*format){ |
| 142 | case 'c': { |
| 143 | format++; |
| 144 | auto arg = (char) va_arg(args, int /* char promotes to int */); |
| 145 | WriteN(&arg, 1); |
| 146 | break; |
| 147 | } case 'Y': { |
| 148 | format++; |
| 149 | auto arg = (bool)va_arg(args, unsigned int); |
| 150 | Write(arg ? "yes" : "no"); |
| 151 | break; |
| 152 | } case 's': { |
| 153 | format++; |
| 154 | auto arg = va_arg(args, const char*); |
| 155 | size_t len = strlen(arg); |
| 156 | WriteN(arg, len); |
| 157 | break; |
| 158 | } case 'd': |
| 159 | case 'i': { |
| 160 | format++; |
| 161 | long arg = va_arg(args, long); |
| 162 | if(arg < 0){ |
| 163 | WriteN("-", 1); |
| 164 | Write(-arg, false); |
| 165 | } else { |
| 166 | Write(arg, false); |
| 167 | } |
| 168 | break; |
| 169 | } case 'u': { |
| 170 | hex = false; |
| 171 | [[fallthrough]]; |
| 172 | } case 'x': { |
| 173 | format++; |
| 174 | auto arg = va_arg(args, unsigned long long); |
| 175 | Write(arg, hex); |
| 176 | break; |
| 177 | } default: |
| 178 | format = format_begun_at; |
| 179 | size_t len = strlen(format); |
| 180 | WriteN(format, len); |
| 181 | format += len; |