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" สำหรับรายละเอียดเพิ่มเติม
ฉันต้องการ printf แบบดรอปอินโดเมนสาธารณะไฟล์เดียวที่มีขนาดต่ำกว่า 1KB ในการกำหนดค่าขั้นต่ำ (โปรแกรมโหลดบูต ฯลฯ) และต่ำกว่า 3KB โดยเปิดใช้งานระฆังและนกหวีดทศนิยม
ในการทำงานเฟิร์มแวร์ โดยทั่วไปฉันต้องการการจัดรูปแบบสตริงของ stdio โดยไม่ต้องใช้ syscall หรือข้อกำหนดเลเยอร์ตัวอธิบายไฟล์ แทบไม่เคยจำเป็นเลยในระบบขนาดเล็กที่คุณต้องการล็อกอินเข้าสู่บัฟเฟอร์ขนาดเล็กหรือปล่อยสัญญาณไปยังบัสโดยตรง นอกจากนี้ การใช้งาน stdio แบบฝังจำนวนมากมีขนาดใหญ่หรือช้ากว่าที่ควรจะเป็น ซึ่งเป็นสิ่งสำคัญสำหรับการทำงานของ bootloader หากคุณไม่ต้องการ syscalls หรือ stdio bells + whistles ใดๆ คุณสามารถใช้ 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 0 ไบต์ไม่ได้เป็นส่วนหนึ่งของการนับ
มาตรฐาน C อนุญาตให้ฟังก์ชัน printf ส่งกลับค่าลบในกรณีที่ไม่สามารถดำเนินการเข้ารหัสสตริงหรืออักขระได้ หรือหากสตรีมเอาต์พุตพบ EOF เนื่องจาก nanoprintf ไม่สนใจทรัพยากรระบบปฏิบัติการ เช่น ไฟล์ และไม่รองรับตัวแก้ไขความยาว l
สำหรับการรองรับ wchar_t
ข้อผิดพลาดรันไทม์ใดๆ อาจเป็นข้อบกพร่องภายใน (โปรดรายงาน!) หรือการใช้งานที่ไม่ถูกต้อง ด้วยเหตุนี้ nanoprintf จึงส่งคืนเฉพาะค่าที่ไม่เป็นลบซึ่งแสดงถึงจำนวนไบต์ที่สตริงที่จัดรูปแบบมี (ลบด้วยไบต์ที่สิ้นสุดด้วยค่า null อีกครั้ง)
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
สำหรับ Sandbox nanoprintf
หากไม่มีการระบุการตั้งค่าสถานะ 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 จะถูกเขียนไปยังไบต์สุดท้ายของบัฟเฟอร์ หากบัฟเฟอร์มีค่าเป็น null
หรือเป็นศูนย์ จะไม่มีการเขียนไบต์
หากคุณกำหนด NANOPRINTF_SNPRINTF_SAFE_EMPTY_STRING_ON_OVERFLOW
และสตริงของคุณมีขนาดใหญ่กว่าบัฟเฟอร์ ไบต์ แรก ของบัฟเฟอร์จะถูกเขียนทับด้วยไบต์ที่สิ้นสุดด้วยค่า null สิ่งนี้มีความคล้ายคลึงกับ snprintf_s ของ Microsoft
ในทุกกรณี nanoprintf จะส่งคืนจำนวนไบต์ที่จะเขียนลงในบัฟเฟอร์ หากมีที่ว่างเพียงพอ ค่านี้ไม่ได้คำนึงถึงไบต์ที่สิ้นสุดด้วยค่า null ตามมาตรฐาน 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
สำหรับ float vararg width (หมายเหตุ: จากนั้นจะถูกเหวี่ยงลงไป double
)
l
: ใช้ความกว้าง vararg long
, double
หรือแบบกว้าง
hh
: ใช้ char
สำหรับความกว้าง vararg แบบอินทิกรัลและการเขียนกลับ
ll
: (ตัวระบุขนาดใหญ่) ใช้ long long
สำหรับความกว้างของปริพันธ์และการเขียนกลับ vararg
j
: (ตัวระบุขนาดใหญ่) ใช้ประเภท [u]intmax_t
สำหรับความกว้าง vararg แบบอินทิกรัลและการเขียนกลับ
z
: (ตัวระบุขนาดใหญ่) ใช้ประเภท size_t
สำหรับความกว้าง vararg แบบอินทิกรัลและการเขียนกลับ
t
: (ตัวระบุขนาดใหญ่) ใช้ประเภท ptrdiff_t
สำหรับความกว้าง vararg แบบอินทิกรัลและการเขียนกลับ
ตัวระบุการแปลง
ตรงกับข้อใดข้อหนึ่งต่อไปนี้:
%
: ตัวอักษรเครื่องหมายเปอร์เซ็นต์
c
: ตัวละคร
s
: สตริงที่สิ้นสุดด้วยค่า Null
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 สามารถจัดรูปแบบ float บนสถาปัตยกรรม soft-float เช่น Cortex-M0 ได้อย่างมีประสิทธิภาพ เพื่อให้ทำงานเหมือนกันโดยมีหรือไม่มีการเพิ่มประสิทธิภาพ เช่น "fast math" และเพื่อลดปริมาณการใช้โค้ด
ตัวระบุ %e
/ %E
, %a
/ %A
และ %g
/ %G
มีการแยกวิเคราะห์แต่ไม่ได้จัดรูปแบบ หากใช้ ผลลัพธ์จะเหมือนกับหากใช้ %f
/ %F
ยินดีต้อนรับคำขอดึง! -
ไม่มีการรองรับอักขระแบบกว้าง: ฟิลด์ %lc
และ %ls
ต้องการให้แปลง arg เป็นอาร์เรย์ถ่านเหมือนกับว่าโดยการเรียกไปยัง wcrtomb เมื่อการแปลงภาษาและชุดอักขระเข้ามาเกี่ยวข้อง เป็นการยากที่จะรักษาชื่อ "นาโน" ดังนั้น %lc
และ %ls
จึงมีพฤติกรรมเหมือน %c
และ %s
ตามลำดับ
ปัจจุบันการแปลงทศนิยมเพียงอย่างเดียวที่สนับสนุนคือรูปแบบทศนิยม: %f
และ %F
ยินดีต้อนรับคำขอดึง!
CI build ได้รับการตั้งค่าให้ใช้ 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 Actions สำหรับบิวด์การรวมอย่างต่อเนื่องทั้งหมด GitHub Linux บิวด์ใช้อิมเมจ Docker นี้จากที่เก็บ Docker ของฉัน
เมทริกซ์จะสร้าง [Debug, Release] x [32-bit, 64-bit] x [Mac, Windows, Linux] x [gcc, clang, msvc] ลบด้วยการกำหนดค่า clang Mac 32-bit
ชุดทดสอบหนึ่งชุดคือทางแยกจากชุดทดสอบ printf ซึ่งได้รับอนุญาตจาก MIT มันมีอยู่เป็นโมดูลย่อยสำหรับวัตถุประสงค์ในการออกใบอนุญาต - nanoprintf เป็นสาธารณสมบัติ ดังนั้นชุดทดสอบนี้จึงเป็นทางเลือกและไม่รวมไว้ตามค่าเริ่มต้น หากต้องการสร้าง ให้เรียกคืนโดยอัปเดตโมดูลย่อยและเพิ่มแฟล็ก --paland
ให้กับการเรียกใช้ ./b
b ของคุณ ไม่จำเป็นต้องใช้ nanoprintf เลย
แนวคิดพื้นฐานของการแปลง float-to-int ได้รับแรงบันดาลใจจาก float -> อัลกอริธึมคงที่ของ Wojciech Muła 64:64 และขยายเพิ่มเติมโดยการเพิ่มการปรับขนาดแบบไดนามิกและความกว้างจำนวนเต็มที่กำหนดค่าได้โดย Oskars Rubenis
ฉันย้ายชุดทดสอบ printf ไปที่ nanoprintf เดิมทีมาจากโค้ดเบสโปรเจ็กต์ mpaland printf แต่นำมาใช้และปรับปรุงโดย Eyal Rozenberg และคนอื่นๆ (Nanoprintf มีการทดสอบของตัวเองมากมาย แต่การทดสอบเหล่านี้ก็ละเอียดและดีมากเช่นกัน!)
การใช้งานไบนารี่นั้นเป็นไปตามข้อกำหนดที่ระบุโดยข้อเสนอ N2630 ของ Jörg Wunsch หวังว่าจะได้รับการยอมรับใน C23!