Hallo,
keine Frage sondern eine gefundene Lösung. Betrifft avr-gcc ab Version
9, mit -std==c++17, C++-Programmierung, meist mit ATmega32U4 (Arduino
Pro Micro oder Leonardo) oder auch v-usb.
Will man USB-Stringdeskriptoren erstellen bereitet das Abzählen der
UTF-16-Buchstaben einige Mühe. Hier helfen Templates weiter. Dazu die
folgende Lösung, die auch mit allen Zeichen außerhalb 7-bit-ASCII
funktioniert:
1
typedefunsignedcharbyte;
2
3
// strlen geht nur mit char*, hier wird's für char16_t gebraucht
Da mit C++17 auch Umlaute und (wie hier dargestellt) chinesische Zeichen
in Bezeichnern unterstützt werden, kann man davon Gebrauch machen.
Andere Lösungen, die von <code>std::array</code> Gebrauch machen
funktionieren mangels geeigneter Include-Dateien nicht mit avr-gcc.
mm ich weis ja nicht...
Für mich sieht das so aus als wenn du dich unbedingt in c++ austoben
willst.
Ich kann jedenfalls keine Vorteile gegenüber einem herkömmlichen Array
erkennen. Zumal man das auch ganz bequem ins Flash legen kann. Was dein
code ja noch nicht kann.
Ob das alles so richtig ist kann ich schlecht beurteilen, da reichen
meine c++ Kenntnisse nicht. Ich sehe aber eine schliesende Klammer
zuviel.
Einen Vorteil deiner Lösung ist wohl der direkte unicode support. Ich
für meinen Teil arbeite nur mit 0x0409 für Englisch.
// "1" means "https://", "0" means "http://" prefix
19
#undef LP
Das funktioniert hier mit dem älteren gcc 5.30 und -std=C++14. Und,
nein, es geht nicht darum sich in C++ auszutoben sondern les- und
wartbaren Kode zu schreiben, der zudem kürzestmöglichen Maschinenkode
generiert; hier: gar keinen, nur Daten. Schade, dass das (zurzeit) nicht
kürzer und kompakter geht: IMHO gehört das Initialisieren der struct in
seinen Konstruktor, aber genau das geht nicht zusammen mit constexpr.
> les- und wartbaren Kode zu schreiben
Tja... Problem ist halt: damit jemand den Programmcode lesen kann, muss
er wissen, was LP() macht.
Auch wenn du eine gute Doku schreibst - es ist halt ein weiterer Punkt,
in den man sich einarbeiten muss. Bei so einer einfachen Aufgabe lohnt
sich der Einarbeitungsaufwand nicht. Bytes zählen und
Flüchtigkeitsfehler korrigieren geht schneller.
Henrik H. schrieb:> Das mit dem Flash funktioniert so, hier für den> Langing-Page-Url-Deskriptor, wie man ihn für WebUsb> braucht:template<size_t N>struct landingpageurldesc_t{> byte l,t,h,s[N]; // length, type, http/https switch, url-string> operator const byte*() const {return &l;}> };> template<int N>constexpr auto landingpageurldesc_f(byte h,const char*s)> {> landingpageurldesc_t<N>A={};> static_assert(sizeof A<256,"URL too long!");> A.l=sizeof A;> A.t=3; // Descriptor type: string (really!)> A.h=h; // protocol, 0=http, 1=https> for (int i=0;i<N;i++) A.s[i]=s[i];> return A;> }> #define LP(h,s) (landingpageurldesc_f<length(u8##s)>(h,u8##s))> static PROGMEM constexpr auto LandingPageUrlDesc> = LP(1,"www.tu-chemnitz.de/~heha/app.htm");> // "1" means "https://", "0" means "http://" prefix> #undef LP> Das funktioniert hier mit dem älteren gcc 5.30 und -std=C++14. Und,> nein, es geht nicht darum sich in C++ auszutoben sondern les- und> wartbaren Kode zu schreiben, der zudem kürzestmöglichen Maschinenkode> generiert; hier: gar keinen, nur Daten. Schade, dass das (zurzeit) nicht> kürzer und kompakter geht: IMHO gehört das Initialisieren der struct in> seinen Konstruktor, aber genau das geht nicht zusammen mit constexpr.
Les und wartbar finde ich das nicht. Warum man z.B. das Element l und
nicht Length nennen konnte, verstehe ich nicht.
Kurzer Code im Eeprom, das ist Ok. Aber das hat nichts mit
Variablennamen im Sourcecode zu tun. Im Sourcecode hat man genug Platz
für viele Kommentare und aussagekräftige Variablennamen
Genauso mit
A.t=3; // Descriptor type: string (really!)
Warum kann man man t nicht als DescriptorType schreiben? Schlimmer aber
noch diese 3. Was macht die 3? Klarer wäre ein Enum:
enum
{
Type_Device = 1,
Type_Configuration = 2,
Type_String = 3,
};
usw.
Aber so ist das kryptisch und unwartbar.
Ich arbeite mit den USB-Descriptoren, die von STM bereitgestellt wurden.
Die sind im Sourcecode einiges länger. Man kann sie aber verstehen und
ändern.
> Les und wartbar finde ich das nicht.> Warum man z.B. das Element l und nicht Length nennen konnte...
Nehmen wir mal einen ganz anderen Bereich - statische Berechnung im
Bauwesen.
Dort sind diese ganzen Formalitäten in den Normen festgelegt. "g" steht
immer für konstante Lasten. "q" steht immer für veränderliche Lasten.
Auch die Schritte der Berechnungen sind in den Normen festgelegt. Alle
statischen Berechnungen sind gleich aufgebaut.
Wird ein Gebäude umgebaut, kann jeder Statiker die Berechnungen seines
Vorgängers lesen und abändern.
Aber der Preis für die Verständlichkeit und Wartbarkeit ist halt: Henrik
H. muss seine Ideen bei der ISO einreichen und es dauert Jahre, bis wir
sein Konzept benutzen können.
Wie man es dreht und wendet - es ist immer verkehrt. Legt jeder selbst
fest, was er als verständlich und wartbar bezeichnet, versteht niemand
die Programme des anderen. Einigen wir uns, braucht jeder Fortschritt
Jahrzehnte.
Noch ein Kommentar schrieb:> Legt jeder selbst fest, was er als verständlich und wartbar bezeichnet
Nein! Einzelkämpfer will keine Firma haben, jedenfalls keine die ich
kenne.
Jedes Team legt das gemeinsam fest. Und vernünftigerweise diskutiert
man nur die Details, die wirklich weh tun oder Zeit/Geld kosten. Wenn
Leute z.B. über Leerzeichen hinterm Komma oder Zeilenumbrüche vor
geschweiften Klammern diskutieren, verlasse ich den Raum und arbeite an
etwas das Geld einbringt (weil es mir Scheißegal ist).