printk.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //
  2. // Created by longjin on 2022/1/22.
  3. //
  4. #include "printk.h"
  5. int skip_and_atoi(const char **s)
  6. {
  7. /**
  8. * @brief 获取连续的一段字符对应整数的值
  9. * @param:**s 指向 指向字符串的指针 的指针
  10. */
  11. int ans = 0;
  12. while (is_digit(**s))
  13. {
  14. ans = ans * 10 + (**s) - '0';
  15. ++(*s);
  16. }
  17. return ans;
  18. }
  19. int vsprintf(char *buf, const char *fmt, va_list args)
  20. {
  21. /**
  22. * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
  23. * @param buf 结果缓冲区
  24. * @param fmt 格式化字符串
  25. * @param args 内容
  26. * @return 最终字符串的长度
  27. */
  28. char *str, *s;
  29. str = buf;
  30. int flags; // 用来存储格式信息的bitmap
  31. int field_width; //区域宽度
  32. int precision; //精度
  33. int qualifier; //数据显示的类型
  34. int len;
  35. //开始解析字符串
  36. for (; *fmt; ++fmt)
  37. {
  38. //内容不涉及到格式化,直接输出
  39. if (*fmt != '%')
  40. {
  41. *str = *fmt;
  42. ++str;
  43. }
  44. //开始格式化字符串
  45. //清空标志位和field宽度
  46. field_width = flags = 0;
  47. ++fmt;
  48. bool flag_tmp = true;
  49. bool flag_break = false;
  50. while (flag_tmp)
  51. {
  52. switch (*fmt)
  53. {
  54. case '\0':
  55. //结束解析
  56. flag_break = true;
  57. flag_tmp = false;
  58. break;
  59. case '%':
  60. //输出 %
  61. *str = '%';
  62. ++str;
  63. ++fmt;
  64. flag_break = true;
  65. break;
  66. case '-':
  67. // 左对齐
  68. flags |= LEFT;
  69. ++fmt;
  70. break;
  71. case '+':
  72. //在正数前面显示加号
  73. flags |= PLUS;
  74. ++fmt;
  75. break;
  76. case ' ':
  77. flags |= SPACE;
  78. ++fmt;
  79. break;
  80. case '#':
  81. //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
  82. flags |= SPECIAL;
  83. ++fmt;
  84. break;
  85. case '0':
  86. //显示的数字之前填充‘0’来取代空格
  87. flags |= PAD_ZERO;
  88. ++fmt;
  89. break;
  90. default:
  91. flag_tmp = false;
  92. break;
  93. }
  94. }
  95. if (flag_break)
  96. break;
  97. //获取区域宽度
  98. if (*fmt == '*')
  99. {
  100. field_width = va_arg(args, int);
  101. ++fmt;
  102. }
  103. else if (is_digit(*fmt))
  104. field_width = skip_and_atoi(&fmt);
  105. //获取小数精度
  106. if (*fmt == '.')
  107. {
  108. ++fmt;
  109. if (*fmt == '*')
  110. {
  111. precision = va_arg(args, int);
  112. ++fmt;
  113. }
  114. else if is_digit (*fmt)
  115. {
  116. precision = skip_and_atoi(&fmt);
  117. }
  118. }
  119. //获取要显示的数据的类型
  120. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
  121. {
  122. qualifier = *fmt;
  123. ++fmt;
  124. }
  125. //转化成字符串
  126. switch (*fmt)
  127. {
  128. // 显示一个字符
  129. case 'c':
  130. //靠右对齐
  131. if (!(flags & LEFT))
  132. {
  133. while (--field_width)
  134. {
  135. *str = ' ';
  136. ++str;
  137. }
  138. }
  139. else //靠左对齐
  140. {
  141. *str = (char)va_arg(args, int);
  142. ++str;
  143. --field_width;
  144. }
  145. while (--field_width)
  146. {
  147. *str = ' ';
  148. ++str;
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. }
  155. }