يعد nanoprintf تطبيقًا غير مرتبط بـ snprintf وvsnprintf للأنظمة المدمجة التي تهدف، عند تمكينها بالكامل، إلى الامتثال لمعايير C11. الاستثناءات الأساسية هي الفاصلة العائمة والترميز العلمي ( %e
, %g
, %a
) والتحويلات التي تتطلب وجود wcrtomb
. يتم دعم إخراج عدد صحيح ثنائي C23 اختياريًا وفقًا لـ N2630. يمكن تكوين ملحقات الأمان لـ snprintf وvsnprintf بشكل اختياري لإرجاع سلاسل مقطوعة أو فارغة تمامًا في أحداث تجاوز سعة المخزن المؤقت.
بالإضافة إلى ذلك، يمكن استخدام nanoprintf لتحليل سلاسل تنسيق نمط printf لاستخراج المعلمات المختلفة ومحددات التحويل، دون القيام بأي تنسيق فعلي للنص.
لا يقوم nanoprintf بإجراء أي تخصيصات للذاكرة ويستخدم أقل من 100 بايت من المكدس. يتم تجميعه إلى ما بين 740 إلى 2640 بايت تقريبًا من كود الكائن على بنية Cortex-M0، اعتمادًا على التكوين.
تتم كتابة كافة التعليمات البرمجية في لهجة الحد الأدنى من C99 لتحقيق أقصى قدر من التوافق للمترجم، ويتم تجميعها بشكل نظيف على أعلى مستويات التحذير على clang + gcc + msvc، ولا تثير أي مشاكل من UBsan أو Asan، ويتم اختبارها بشكل شامل على بنيات 32 بت و64 بت . يتضمن nanoprintf رؤوس C القياسية ولكنه يستخدمها فقط لأنواع C99 وقوائم الوسائط؛ لا يتم إجراء أي استدعاءات إلى stdlib / libc، باستثناء أي استدعاءات حسابية داخلية ذات أعداد صحيحة كبيرة قد يصدرها المترجم الخاص بك. كالعادة، تكون بعض الرؤوس الخاصة بنظام التشغيل Windows مطلوبة إذا كنت تقوم بالتجميع أصليًا لـ msvc.
nanoprintf هو ملف ذو رأس واحد بأسلوب مكتبات stb. أما باقي المستودع فهو عبارة عن اختبارات وسقالات وغير مطلوب للاستخدام.
يعد nanoprintf قابلاً للتكوين بشكل ثابت حتى يتمكن المستخدمون من إيجاد توازن بين الحجم ومتطلبات المترجم ومجموعة الميزات. تحويل الفاصلة العائمة، ومعدلات الطول "الكبيرة"، وإعادة كتابة الحجم كلها قابلة للتكوين ولا يتم تجميعها إلا إذا طلب ذلك صراحةً، راجع التكوين للحصول على التفاصيل.
أضف التعليمة البرمجية التالية إلى أحد ملفاتك المصدرية لتجميع تطبيق nanoprintf:
// define your nanoprintf configuration macros here (see "Configuration" below) #define NANOPRINTF_IMPLEMENTATION #include "path/to/nanoprintf.h"
بعد ذلك، في أي ملف تريد استخدام nanoprintf فيه، ما عليك سوى تضمين الرأس واستدعاء وظائف npf_:
#include "nanoprintf.h" void print_to_uart(void) { npf_pprintf(&my_uart_putc, NULL, "Hello %s%c %d %u %fn", "worl", 'd', 1, 2, 3.f); } void print_to_buf(void *buf, unsigned len) { npf_snprintf(buf, len, "Hello %s", "world"); }
راجع أمثلة "استخدام nanoprintf مباشرة" و"Wrap nanoprintf" لمزيد من التفاصيل.
كنت أرغب في طباعة ملف واحد للنطاق العام يأتي بحجم أقل من 1 كيلو بايت في الحد الأدنى من التكوين (برامج تحميل التشغيل وما إلى ذلك)، وأقل من 3 كيلو بايت مع تمكين أجراس وصفارات الفاصلة العائمة.
في عمل البرامج الثابتة، أرغب عمومًا في تنسيق سلسلة stdio دون متطلبات طبقة syscall أو واصف الملف؛ لا تكون هناك حاجة إليها أبدًا في الأنظمة الصغيرة حيث تريد تسجيل الدخول إلى مخازن مؤقتة صغيرة أو الإرسال مباشرة إلى الحافلة. كما أن العديد من تطبيقات stdio المضمنة تكون أكبر أو أبطأ مما تحتاج إليه، وهذا أمر مهم لعمل أداة تحميل التشغيل. إذا لم تكن بحاجة إلى أي من مكالمات النظام أو أجراس + صفارات stdio، فيمكنك ببساطة استخدام nanoprintf و nosys.specs
وتقليص حجم جهازك.
تم تحسين هذا الرمز من حيث الحجم، وليس من حيث سهولة القراءة أو البنية. لسوء الحظ، فإن النمطية و"النظافة" (مهما كان ذلك يعني) تضيف عبئًا على هذا النطاق الصغير، لذلك يتم دفع معظم الوظائف والمنطق معًا في npf_vpprintf
. ليس هذا هو الشكل الذي ينبغي أن تبدو عليه تعليمات برمجية الأنظمة المضمنة العادية؛ إنه حساء #ifdef
ويصعب فهمه، وأعتذر إذا كان عليك التجول في التنفيذ. نأمل أن تكون الاختبارات المختلفة بمثابة قضبان إرشادية إذا قمت باختراقها.
بالتناوب، ربما أنت مبرمج أفضل مني بكثير! في هذه الحالة، الرجاء مساعدتي في جعل هذا الرمز أصغر حجمًا وأكثر وضوحًا دون زيادة حجم البصمة، أو دفعي في الاتجاه الصحيح. :)
لدى nanoprintf 4 وظائف رئيسية:
npf_snprintf
: استخدم مثل snprintf.
npf_vsnprintf
: استخدم مثل vsnprintf (دعم va_list
).
npf_pprintf
: استخدم مثل printf مع رد الاتصال بالكتابة لكل حرف (semihosting، UART، إلخ).
npf_vpprintf
: يُستخدم مثل npf_pprintf
ولكنه يأخذ va_list
.
تأخذ أشكال pprintf
رد اتصال يتلقى الحرف المراد طباعته ومؤشر سياق يوفره المستخدم.
قم بتمرير NULL
أو nullptr
إلى npf_[v]snprintf
لعدم كتابة أي شيء، وإرجاع طول السلسلة المنسقة فقط.
لا يوفر nanoprintf printf
أو putchar
نفسه؛ يُنظر إليها على أنها خدمات على مستوى النظام وNanoprintf عبارة عن مكتبة أدوات مساعدة. من المأمول أن يكون nanoprintf لبنة بناء جيدة لطباعة printf
الخاصة.
تُرجع جميع وظائف nanoprintf نفس القيمة: عدد الأحرف التي تم إرسالها إما إلى رد الاتصال (لـ npf_pprintf) أو عدد الأحرف التي كان سيتم كتابتها إلى المخزن المؤقت مع توفير مساحة كافية. البايت null-terminator 0 ليس جزءًا من العدد.
يسمح معيار C لوظائف printf بإرجاع قيم سالبة في حالة تعذر تنفيذ سلسلة أو ترميز أحرف، أو إذا واجه دفق الإخراج EOF. نظرًا لأن nanoprintf غافل عن موارد نظام التشغيل مثل الملفات، ولا يدعم معدل الطول l
لدعم wchar_t
، فإن أي أخطاء في وقت التشغيل هي إما أخطاء داخلية (يُرجى الإبلاغ عنها!) أو استخدام غير صحيح. ولهذا السبب، تقوم تقنية nanoprintf بإرجاع القيم غير السالبة التي تمثل عدد البايتات التي تحتوي عليها السلسلة المنسقة (مرة أخرى، مطروحًا منها بايت الإنهاء الخالي).
يحتوي nanoprintf على علامات التكوين الثابتة التالية.
NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين محددات عرض الحقل.
NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين محددات الدقة.
NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين محددات الفاصلة العائمة.
NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين المعدلات كبيرة الحجم.
NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين المحددات الثنائية.
NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS
: اضبط على 0
أو 1
. تمكين %n
من إعادة الكتابة.
NANOPRINTF_VISIBILITY_STATIC
: تعريف اختياري. وضع علامة على النماذج الأولية على أنها static
في وضع الحماية النانوي.
إذا لم يتم تحديد أي علامات تكوين، فسيتم تعيين القيم الافتراضية لـ nanoprintf على القيم المضمنة "المعقولة" في محاولة لتكون مفيدة: يتم تمكين العوامات، ولكن يتم تعطيل عمليات إعادة الكتابة والتنسيقات الثنائية والكبيرة. إذا تم تحديد أي علامات تكوين بشكل صريح، فإن nanoprintf يتطلب تحديد جميع العلامات بشكل صريح.
إذا تم استخدام ميزة محدد التنسيق المعطلة، فلن يحدث أي تحويل وستتم طباعة سلسلة محدد التنسيق بدلاً من ذلك.
يحتوي nanoprintf على تعريف التكوين المحدد للفاصلة العائمة التالي.
NANOPRINTF_CONVERSION_BUFFER_SIZE
: اختياري، القيمة الافتراضية هي 23
. يضبط حجم المخزن المؤقت للأحرف المستخدم لتخزين القيمة المحولة. قم بالتعيين على رقم أكبر لتمكين طباعة أرقام الفاصلة العائمة بعدد أكبر من الأحرف. يتضمن حجم المخزن المؤقت الجزء الصحيح وجزء الكسر والفاصل العشري، ولكنه لا يتضمن الإشارة وأحرف الحشو. إذا لم يتم احتواء الرقم في المخزن المؤقت، فسيتم طباعة err
. كن حذرًا مع الأحجام الكبيرة حيث يتم تخصيص المخزن المؤقت للتحويل على ذاكرة المكدس.
NANOPRINTF_CONVERSION_FLOAT_TYPE
: اختياري، القيمة الافتراضية هي unsigned int
. يضبط نوع العدد الصحيح المستخدم في خوارزمية التحويل العائمة، والتي تحدد دقة التحويل. يمكن ضبطه على أي نوع عدد صحيح غير موقّع، مثل uint64_t
أو uint8_t
على سبيل المثال.
افتراضيًا، يتصرف npf_snprintf وnpf_vsnprintf وفقًا لمعيار C: سيتم ملء المخزن المؤقت المقدم ولكن لن يتم تجاوزه. إذا كانت السلسلة قد تجاوزت المخزن المؤقت، فسيتم كتابة بايت فاصل فارغ إلى البايت الأخير من المخزن المؤقت. إذا كان المخزن المؤقت null
أو بحجم صفر، فلن يتم كتابة أي بايت.
إذا قمت بتعريف NANOPRINTF_SNPRINTF_SAFE_EMPTY_STRING_ON_OVERFLOW
وكانت السلسلة الخاصة بك أكبر من المخزن المؤقت الخاص بك، فسيتم استبدال البايت الأول من المخزن المؤقت ببايت فاصل خالٍ. وهذا مشابه من حيث الروح لـ snprintf_s من Microsoft.
في جميع الحالات، ستعيد تقنية nanoprintf عدد البايتات التي كان سيتم كتابتها إلى المخزن المؤقت، لو كانت هناك مساحة كافية. لا تأخذ هذه القيمة في الاعتبار بايتة الإنهاء الخالية، وفقًا لمعيار C.
يستخدم nanoprintf الذاكرة المكدسة فقط ولا يستخدم أي عناصر أولية متزامنة، لذا فهو غافل داخليًا عن بيئة التنفيذ الخاصة به. وهذا يجعل من الآمن الاتصال من سياقات تنفيذ متعددة بشكل متزامن، أو مقاطعة استدعاء npf_
باستدعاء npf_
آخر (على سبيل المثال، ISR أو شيء من هذا القبيل). إذا كنت تستخدم npf_pprintf
بشكل متزامن مع نفس هدف npf_putc
، فالأمر متروك لك للتأكد من الصحة داخل رد الاتصال الخاص بك. إذا قمت npf_snprintf
من عدة سلاسل رسائل إلى نفس المخزن المؤقت، فسيكون لديك سباق بيانات واضح.
كما هو الحال مع printf
، تتوقع nanoprintf
سلسلة مواصفات تحويل بالشكل التالي:
[flags][field width][.precision][length modifier][conversion specifier]
أعلام
لا شيء أو أكثر مما يلي:
0
: قم بملء الحقل بأحرف صفرية بادئة.
-
: قم بضبط نتيجة التحويل في الحقل على اليسار.
+
: التحويلات الموقعة تبدأ دائمًا بأحرف +
أو -
.
: (مسافة) يتم إدراج حرف مسافة إذا لم يكن الحرف المحول الأول علامة.
#
: يكتب أحرفًا إضافية ( 0x
للأرقام السداسية، .
للأعداد الفارغة، و'0' للأعداد الثمانية الفارغة، وما إلى ذلك).
عرض الحقل (إذا كان ممكّنًا)
يضيف الرقم الذي يحدد إجمالي عرض الحقل للتحويل حشوة. إذا كان عرض الحقل هو *
، تتم قراءة عرض الحقل من vararg التالي.
الدقة (إذا تم تمكينها)
مسبوقة بـ .
، رقم يحدد دقة الرقم أو السلسلة. إذا كانت الدقة *
، فستتم قراءة الدقة من vararg التالي.
معدّل الطول
لا شيء أو أكثر مما يلي:
h
: استخدم short
لعرض vararg المتكامل وإعادة الكتابة.
L
: استخدم long double
لعرض vararg العائم (ملاحظة: سيتم بعد ذلك تحويله إلى double
)
l
: استخدم عرضًا long
أو double
أو واسعًا.
hh
: استخدم char
لعرض vararg المتكامل والكتابة الخلفية.
ll
: (محدد كبير) استخدم long long
لعرض vararg المتكامل والكتابة الخلفية.
j
: (محدد كبير) استخدم الأنواع [u]intmax_t
لعرض vararg المتكامل وإعادة الكتابة.
z
: (محدد كبير) استخدم أنواع size_t
لعرض vararg المتكامل وإعادة الكتابة.
t
: (محدد كبير) استخدم أنواع ptrdiff_t
لعرض vararg المتكامل وإعادة الكتابة.
محدد التحويل
بالضبط واحد مما يلي:
%
: علامة النسبة المئوية الحرفية
c
: الشخصية
s
: سلاسل منتهية بقيمة خالية
i
/ d
: الأعداد الصحيحة الموقعة
u
: الأعداد الصحيحة غير الموقعة
o
: الأعداد الصحيحة الثماني غير الموقعة
x
/ X
: الأعداد الصحيحة السداسية العشرية غير الموقعة
p
: المؤشرات
n
: اكتب عدد البايتات المكتوبة على المؤشر vararg
f
/ F
: العلامة العشرية العائمة
e
/ E
: النقطة العائمة العلمية (غير منفذة، طباعة عشرية عائمة)
g
/ G
: أقصر نقطة عائمة (غير منفذة، طباعة عشرية عائمة)
a
/ A
: النقطة العائمة السداسية (غير منفذة، تطبع عدد عشري عائم)
b
/ B
: الأعداد الصحيحة الثنائية
يتم إجراء تحويل الفاصلة العائمة عن طريق استخراج الأجزاء الصحيحة والكسرية من الرقم إلى متغيرين صحيحين منفصلين. يتم بعد ذلك تحجيم الأس لكل جزء من الأساس 2 إلى الأساس 10 عن طريق ضرب وتقسيم الجزء العشري بشكل متكرر على 2 و5 بشكل مناسب. يتم تحديد ترتيب عمليات القياس ديناميكيًا (اعتمادًا على القيمة) للاحتفاظ بأكبر قدر ممكن من الأجزاء الأكثر أهمية في الجزء العشري. كلما ابتعدت القيمة عن الفاصل العشري، زاد الخطأ في القياس. مع عرض نوع عدد صحيح للتحويل يبلغ N
بت في المتوسط، تحتفظ الخوارزمية N - log2(5)
أو N - 2.322
بت من الدقة. بالإضافة إلى ذلك، يتم تحويل الأجزاء الصحيحة التي تصل إلى 2 ^^ N - 1
والأجزاء الكسرية التي تصل إلى N - 2.322
بت بعد الفاصل العشري بشكل مثالي دون فقدان أي بتات.
نظرًا لأن التعليمات البرمجية الثابتة -> تعمل على بتات القيمة العائمة الأولية، فلا يتم تنفيذ أي عمليات فاصلة عائمة. يسمح هذا لـ nanoprintf بتنسيق العوامات بكفاءة على بنيات التعويم الناعم مثل Cortex-M0، للعمل بشكل متطابق مع أو بدون تحسينات مثل "الرياضيات السريعة"، ولتقليل أثر التعليمات البرمجية.
تم تحليل المحددات %e
/ %E
و %a
/ %A
و %g
/ %G
ولكن لم يتم تنسيقها. إذا تم استخدامه، فسيكون الإخراج مطابقًا لما إذا تم استخدام %f
/ %F
. نرحب بطلبات السحب! :)
لا يوجد دعم للأحرف العريضة: يتطلب الحقلان %lc
و %ls
تحويل الوسيطة إلى مصفوفة أحرف كما لو كان ذلك عن طريق استدعاء wcrtomb. عندما يتعلق الأمر بتحويلات اللغة ومجموعة الأحرف، فمن الصعب الاحتفاظ بالاسم "nano". وفقًا لذلك، يتصرف %lc
و %ls
مثل %c
و %s
على التوالي.
التحويلات العائمة الوحيدة المدعومة حاليًا هي الأشكال العشرية: %f
و %F
. نرحب بطلبات السحب!
تم إعداد بنية CI لاستخدام gcc وnm لقياس الحجم المترجم لكل طلب سحب. راجع مخرجات مهمة "تقارير حجم" عمليات التحقق المسبق لعمليات التشغيل الأخيرة.
يتم أخذ قياسات الحجم التالية مقابل بنية Cortex-M0.
Configuration "Minimal": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - arm-none-eabi-nm --print-size --size-sort npf.o 00000046 00000002 t npf_bufputc_nop 00000048 00000010 t npf_putc_cnt 00000032 00000014 t npf_bufputc 00000270 00000016 T npf_pprintf 000002cc 00000016 T npf_snprintf 00000000 00000032 t npf_utoa_rev 00000286 00000046 T npf_vsnprintf 00000058 00000218 T npf_vpprintf Total size: 0x2e2 (738) bytes Configuration "Binary": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - arm-none-eabi-nm --print-size --size-sort npf.o 00000046 00000002 t npf_bufputc_nop 00000048 00000010 t npf_putc_cnt 00000032 00000014 t npf_bufputc 000002a8 00000016 T npf_pprintf 00000304 00000016 T npf_snprintf 00000000 00000032 t npf_utoa_rev 000002be 00000046 T npf_vsnprintf 00000058 00000250 T npf_vpprintf Total size: 0x31a (794) bytes Configuration "Field Width + Precision": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - arm-none-eabi-nm --print-size --size-sort npf.o 00000046 00000002 t npf_bufputc_nop 00000048 00000010 t npf_putc_cnt 00000032 00000014 t npf_bufputc 000004fe 00000016 T npf_pprintf 0000055c 00000016 T npf_snprintf 00000000 00000032 t npf_utoa_rev 00000514 00000048 T npf_vsnprintf 00000058 000004a6 T npf_vpprintf Total size: 0x572 (1394) bytes Configuration "Field Width + Precision + Binary": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - arm-none-eabi-nm --print-size --size-sort npf.o 00000046 00000002 t npf_bufputc_nop 00000048 00000010 t npf_putc_cnt 00000032 00000014 t npf_bufputc 00000560 00000016 T npf_pprintf 000005bc 00000016 T npf_snprintf 00000000 00000032 t npf_utoa_rev 00000576 00000046 T npf_vsnprintf 00000058 00000508 T npf_vpprintf Total size: 0x5d2 (1490) bytes Configuration "Float": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - arm-none-eabi-nm --print-size --size-sort npf.o 00000046 00000002 t npf_bufputc_nop 00000048 00000010 t npf_putc_cnt 00000032 00000014 t npf_bufputc 00000618 00000016 T npf_pprintf 00000674 00000016 T npf_snprintf 00000000 00000032 t npf_utoa_rev 0000062e 00000046 T npf_vsnprintf 00000058 000005c0 T npf_vpprintf Total size: 0x68a (1674) bytes Configuration "Everything": arm-none-eabi-gcc -c -x c -Os -I/__w/nanoprintf/nanoprintf -o npf.o -mcpu=cortex-m0 -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=1 - arm-none-eabi-nm --print-size --size-sort npf.o 0000005a 00000002 t npf_bufputc_nop 0000005c 00000010 t npf_putc_cnt 00000046 00000014 t npf_bufputc 000009da 00000016 T npf_pprintf 00000a38 00000016 T npf_snprintf 00000000 00000046 t npf_utoa_rev 000009f0 00000048 T npf_vsnprintf 0000006c 0000096e T npf_vpprintf Total size: 0xa4e (2638) bytes
للحصول على البيئة وإجراء الاختبارات:
استنساخ هذا المستودع أو تفرعه.
قم بتشغيل ./b
من الجذر (أو py -3 build.py
من الجذر، لمستخدمي Windows)
سيؤدي هذا إلى إنشاء كافة اختبارات الوحدة والمطابقة والتجميع لبيئة مضيفك. سيؤدي أي فشل في الاختبار إلى إرجاع رمز خروج غير صفري.
تستخدم بيئة تطوير nanoprintf cmake و ninja. إذا كان لديك هذه العناصر في طريقك، فسيستخدمها ./b
. إذا لم يكن الأمر كذلك، فسيقوم ./b
بتنزيلها ونشرها في path/to/your/nanoprintf/external
.
يستخدم nanoprintf إجراءات GitHub لجميع بنيات التكامل المستمر. تستخدم إصدارات GitHub Linux صورة Docker هذه من مستودع Docker الخاص بي.
تقوم المصفوفة ببناء [Debug, Release] x [32-bit, 64-bit] x [Mac, Windows, Linux] x [gcc, clang, msvc]، بدون تكوينات clang Mac ذات 32 بت.
مجموعة اختبار واحدة عبارة عن شوكة من مجموعة اختبار printf، وهي مرخصة من معهد ماساتشوستس للتكنولوجيا. إنه موجود كوحدة فرعية لأغراض الترخيص - nanoprintf هو مجال عام، لذا فإن مجموعة الاختبار المحددة هذه اختيارية ومستبعدة افتراضيًا. لإنشائه، قم باستعادته عن طريق تحديث الوحدات الفرعية وإضافة علامة --paland
إلى استدعاء ./b
الخاص بك. ليس من الضروري استخدام nanoprintf على الإطلاق.
الفكرة الأساسية للتحويل من float-to-int مستوحاة من خوارزمية Wojciech Muła العائمة -> 64:64 الثابتة وتم توسيعها بشكل أكبر عن طريق إضافة مقياس ديناميكي وعرض عدد صحيح قابل للتكوين بواسطة Oskars Rubenis.
لقد قمت بنقل مجموعة اختبار printf إلى nanoprintf. كان في الأصل من قاعدة بيانات مشروع mpaland printf ولكن تم اعتماده وتحسينه بواسطة Eyal Rozenberg وآخرين. (تمتلك Nanoprintf العديد من الاختبارات الخاصة بها، ولكنها أيضًا شاملة جدًا وجيدة جدًا!)
يعتمد التنفيذ الثنائي على المتطلبات المحددة في اقتراح Jörg Wunsch N2630، والذي نأمل أن يتم قبوله في C23!