29 | tinyendian A minimal library providing functionality for changing the endianness of data.
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/doc/search.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var items = [
3 | {"tinyendian" : "tinyendian.html"},
4 | {"tinyendian.UTFEncoding" : "tinyendian/UTFEncoding.html"},
5 | {"tinyendian.swapByteOrder" : "tinyendian.html#swapByteOrder"},
6 | {"tinyendian.fixUTFByteOrder" : "tinyendian.html#fixUTFByteOrder"},
7 | ];
8 | function search(str) {
9 | var re = new RegExp(str.toLowerCase());
10 | var ret = {};
11 | for (var i = 0; i < items.length; i++) {
12 | var k = Object.keys(items[i])[0];
13 | if (re.test(k.toLowerCase()))
14 | ret[k] = items[i][k];
15 | }
16 | return ret;
17 | }
18 |
19 | function searchSubmit(value, event) {
20 | console.log("searchSubmit");
21 | var resultTable = document.getElementById("results");
22 | while (resultTable.firstChild)
23 | resultTable.removeChild(resultTable.firstChild);
24 | if (value === "" || event.keyCode == 27) {
25 | resultTable.style.display = "none";
26 | return;
27 | }
28 | resultTable.style.display = "block";
29 | var results = search(value);
30 | var keys = Object.keys(results);
31 | if (keys.length === 0) {
32 | var row = resultTable.insertRow();
33 | var td = document.createElement("td");
34 | var node = document.createTextNode("No results");
35 | td.appendChild(node);
36 | row.appendChild(td);
37 | return;
38 | }
39 | for (var i = 0; i < keys.length; i++) {
40 | var k = keys[i];
41 | var v = results[keys[i]];
42 | var link = document.createElement("a");
43 | link.href = v;
44 | link.textContent = k;
45 | link.attributes.id = "link" + i;
46 | var row = resultTable.insertRow();
47 | row.appendChild(link);
48 | }
49 | }
50 |
51 | function hideSearchResults(event) {
52 | if (event.keyCode != 27)
53 | return;
54 | var resultTable = document.getElementById("results");
55 | while (resultTable.firstChild)
56 | resultTable.removeChild(resultTable.firstChild);
57 | resultTable.style.display = "none";
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/doc/show_hide.js:
--------------------------------------------------------------------------------
1 | window.onload = function(e)
2 | {
3 | var elems = document.querySelectorAll( "div.toc ul ul" );
4 | for( i in elems )
5 | {
6 | if( elems[i].style.display != "block" )
7 | elems[i].style.display = "none";
8 | }
9 | }
10 |
11 | function show_hide(id)
12 | {
13 | var elem = document.getElementById( id );
14 | if( elem.style.display == "block" )
15 | elem.style.display = "none";
16 | else elem.style.display = "block";
17 | }
18 |
--------------------------------------------------------------------------------
/doc/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-family: Verdana, "DejaVu Sans", sans;
3 | margin: 0;
4 | padding: 0;
5 | background-color: #333;
6 | border-left: .2em solid #333;
7 | border-right: .2em solid #333;
8 | min-height: 100%;
9 | }
10 |
11 | body {
12 | margin: 0;
13 | padding: 0;
14 | }
15 |
16 | div.main {
17 | overflow: hidden;
18 | background-color: #F8F8F8;
19 | }
20 |
21 |
22 |
23 | /**** BREADCRUMBS ****/
24 |
25 | div.breadcrumbs {
26 | color: white;
27 | background-color: #333;
28 | padding: 1.0em 0.5em 0.0em 0.5em;
29 | left: 0;
30 | box-sizing: border-box;
31 | text-align: right;
32 | top: 0;
33 | width: 100%;
34 | height: 48px;
35 | font-size: 95%;
36 |
37 | position: fixed;
38 | }
39 |
40 | div.breadcrumbs a {
41 | color: white;
42 | }
43 |
44 | div.breadcrumbs span.highlight, div.breadcrumbs span a {
45 | color: #DAAF07;
46 | }
47 |
48 | div.breadcrumbs input {
49 | width: 7em;
50 | margin-top: -0.1em;
51 | }
52 |
53 | div.breadcrumbs small {
54 | font-size: 0.8em;
55 | }
56 |
57 | /** narrow screen hacks **/
58 | @media only screen and (max-width: 1000px)
59 | {
60 | div.breadcrumbs span, div.breadcrumbs small {
61 | font-size: 80%;
62 | }
63 | }
64 | @media only screen and (max-width: 800px)
65 | {
66 | div.breadcrumbs small {
67 | display: none;
68 | position: fixed;
69 | }
70 | div.breadcrumbs span {
71 | font-size: 75%;
72 | }
73 | }
74 | @media only screen and (max-width: 600px)
75 | {
76 | div.breadcrumbs span {
77 | font-size: 65%;
78 | }
79 | }
80 |
81 | div.breadcrumbs a.home {
82 | float: left;
83 | font-weight: bold;
84 | font-size: 200%;
85 | margin: 0 2% 0 0%;
86 | margin-top: -0.3em;
87 | text-decoration: none;
88 | }
89 |
90 | div.breadcrumbs input {
91 | float: left;
92 | }
93 |
94 |
95 | /* anchors need to compensate for the fixed-pos breadcrumbs */
96 | a.anchor
97 | {
98 | display: block;
99 | position: relative;
100 | top: -48px;
101 | visibility: hidden;
102 | }
103 |
104 | /** SEARCH RESULTS **/
105 | #results {
106 | position: absolute;
107 | max-height: 30em;
108 | background-color: #eee;
109 | box-shadow: 0 .25em .25em black;
110 | display: none;
111 | text-align: left;
112 | color: black;
113 | margin-top: 2em;
114 | font-size: 70%;
115 | z-index: 1000;
116 | overflow-y: scroll;
117 | }
118 |
119 | #results a {
120 | color: blue;
121 | }
122 |
123 |
124 | /**** SIDEBAR, TABLE OF CONTENTS ****/
125 |
126 | div.sidebar {
127 | margin-top: 48px;
128 | float: left;
129 | margin-right: -1px;
130 | border-right: 1px solid #D0D0D0;
131 | background-color: #F8F8F0;
132 | }
133 |
134 |
135 | div.toc {
136 | padding: 1.5em 0.75em 1em 0.5em;
137 | font-size: 0.55em;
138 | line-height: 1.95em;
139 | display:block;
140 | }
141 |
142 | @media only screen and (max-width: 800px)
143 | {
144 | div.toc {
145 | font-size: 0.5em;
146 | padding: 1.5em 0.4em 1em 0.2em;
147 | }
148 | }
149 |
150 |
151 | /* stuff for showing/hiding the sidebar */
152 | .hide, .show {
153 | display: block;
154 | float: right;
155 | border-right: 1px solid #D0D0D0;
156 | border-bottom: 1px solid #D0D0D0;
157 | border-left: 1px solid #D0D0D0;
158 | /* to avoid having double border */
159 | margin-right: -1px;
160 | font-size: 1.1em;
161 | padding: 0 0.6em;
162 | }
163 | a.hide, a.show {
164 | color: #111;
165 | text-decoration: none;
166 | }
167 | .hide {
168 | background-color: #F8F8F8;
169 | border-bottom-left-radius:3px;
170 | border-right: 1px solid #F8F8F8;
171 | }
172 | .show {
173 | background-color: #F8F8F0;
174 | border-bottom-right-radius:3px;
175 | display: none;
176 | }
177 | .hide:target + .show {
178 | display: inline;
179 | position: absolute;
180 | }
181 | .hide:target {
182 | display: none;
183 | }
184 | .hide:target ~ .toc {
185 | display:none;
186 | }
187 |
188 |
189 | div.toc .toc-additional {
190 | border-bottom: 1px dashed #333;
191 | line-height: 1.5em;
192 | }
193 |
194 | div.toc .toc-additional p, div.toc .toc-additional ul {
195 | margin: 0.4em 0;
196 | }
197 |
198 | div.toc ul {
199 | list-style-type: none;
200 | padding-left: 0;
201 | padding-bottom: 0.5em;
202 | }
203 |
204 | div.toc ul ul {
205 | list-style-type: none;
206 | padding-left: 0.5em;
207 | }
208 |
209 |
210 | div.toc a {
211 | color: #111;
212 | font-size: 1.25em;
213 | }
214 |
215 | @media only screen and (max-width: 800px)
216 | {
217 | div.toc ul ul {
218 | padding-left: 0.2em;
219 | }
220 | }
221 |
222 | div.toc span.package {
223 | cursor: pointer;
224 | line-height: 1.8em;
225 | font-weight: bold;
226 | border: 1px solid rgba(0, 0, 0, 0.12);
227 | border-radius: 2px;
228 | background-color: #F0F0F0;
229 | font-size: 1.25em;
230 | padding: 0 0.2em;
231 | /* counteracts the text movement caused by the padding */
232 | margin: 0 -0.2em;
233 | }
234 |
235 | div.toc span.package a {
236 | font-size: 1em;
237 | }
238 |
239 | /* Highlight the current module/package */
240 | div.toc .selected {
241 | border-radius: 2px;
242 | background-color: #DAAF07 !important;
243 | padding: 0.325em 0.2em;
244 | /* counteracts the text movement caused by the padding */
245 | margin: -0.325em -0.2em;
246 | }
247 |
248 |
249 |
250 | /**** MAIN CONTENT ****/
251 |
252 | div.content {
253 | margin-top: 48px;
254 | padding: 1.5em;
255 | font-size: 90%;
256 | line-height: 130%;
257 | overflow: hidden;
258 | border-left: 1px solid #D0D0D0;
259 | }
260 | @media only screen and (max-width: 800px)
261 | {
262 | div.content {
263 | font-size: 82%;
264 | }
265 | }
266 | @media only screen and (max-width: 600px)
267 | {
268 | div.content {
269 | font-size: 70%;
270 | padding: 1.5em 0.3em 1.5em 0.5em;
271 | }
272 | }
273 |
274 | div.content h2 {
275 | margin: .35em 0 .45em 0;
276 | padding-top: .35em;
277 | font-size: 1.3em;
278 | }
279 |
280 | div.content h3 {
281 | font-size: 1.1em;
282 | }
283 |
284 | div.content tr {
285 | margin: 0;
286 | }
287 |
288 | div.content table {
289 | border-collapse: collapse;
290 | border-bottom: 1px dashed #333;
291 | font-size: 90%;
292 | line-height: 130%;
293 | margin: 1em 0;
294 | }
295 |
296 | div.content td {
297 | border-top: 1px dashed #333;
298 | margin: 0;
299 | padding: .32em;
300 | }
301 |
302 | div.content td:first-child {
303 | text-align: center;
304 | }
305 |
306 | /* prevent function attribs from wrapping, make the cell wider instead */
307 | div.content td:first-child * {
308 | white-space: nowrap
309 | }
310 |
311 | /* The first markdown-generated paragraph in e.g. Params tables shouldn't add any vertical
312 | * space
313 | */
314 | div.content td p:first-child {
315 | margin: 0;
316 | }
317 |
318 | div.content p strong {
319 | font-size: 92%;
320 | }
321 |
322 | .paramName {
323 | font-weight: bold;
324 | width: 6em;
325 | }
326 |
327 | div.section {
328 | padding: 0;
329 | margin: 0;
330 | }
331 |
332 |
333 |
334 | /**** EXTRA INFO IN FUNCTION/CLASS/ETC LISTS ****/
335 |
336 | div.content td .extrainfo{
337 | display: block;
338 | line-height: 105%;
339 | font-family: monospace;
340 | font-size: 85%;
341 | text-align: center;
342 | }
343 |
344 | .extrainfo div {
345 | display: block;
346 | margin: 0;
347 | }
348 |
349 | .extrainfo .attr-const { color: blueviolet; }
350 | .extrainfo .attr-pure { color: darkslategray; }
351 | .extrainfo .attr-nothrow { color: brown; }
352 | .extrainfo .attr-nogc { color: darkgreen; }
353 | .extrainfo .attr-safe { color: darkblue; }
354 | .extrainfo .attr-trusted { color: firebrick; }
355 | .extrainfo .attr-system { color: darkred; }
356 | .extrainfo .attr-final { color: darkolivegreen; }
357 | .extrainfo .attr-ref { color: fuchsia; }
358 |
359 |
360 | /**** SYMBOLS (not used by the one-file-for-every-variable writer backend) ****/
361 |
362 | div.aggregate-symbol {
363 | display: flex;
364 | flex-direction: column;
365 | display: -webkit-flex;
366 | -webkit-flex-direction: column;
367 | }
368 |
369 | div.aggregate-symbol div.description {
370 | order: -2;
371 | -webkit-order: -2;
372 | }
373 |
374 | div.aggregate-symbol div.members {
375 | order: -1;
376 | -webkit-order: -1;
377 | padding-bottom: 0.3em;
378 | border-bottom: 10px solid #333;
379 | margin: 1em 0em 1.5em 0em;
380 | }
381 |
382 | div.symbol {
383 | border-radius: 3px;
384 | border: 1px solid #d0d0d0;
385 | padding: 1px 0.4em;
386 | margin: 0.5em 0;
387 | }
388 |
389 | a.anchor:target + div.symbol {
390 | border: 2px solid #DAAF07;
391 | border-radius: 0;
392 | background-color: #F8F8F0;
393 | }
394 |
395 |
396 |
397 | /**** SECTION-SPECIFIC STYLES ****/
398 |
399 | .section.seealso, .section.note, .section.imports {
400 | font-size: 75%;
401 | line-height: 135%;
402 | /* background-color: #F0F0C0; */
403 | /* background-color: #DA7F07; */
404 | /* background-color: #DA8F07; */
405 | /* background-color: #DA9F07; */
406 | background-color: #DAAF07;
407 | /* background-color: #EABD08; */
408 | padding: 1em;
409 | margin-bottom: 0.5em;
410 | }
411 |
412 | .section.seealso h2, .section.note h2 {
413 | display: block;
414 | float: left;
415 | margin: 0 0.7em -0.05em 0em;
416 | padding: 0;
417 | font-size: 1.1em;
418 | }
419 |
420 | .section.imports h2 {
421 | display: inline;
422 | margin: 0.5em 0em;
423 | padding: 0;
424 | font-size: 1.1em;
425 | }
426 |
427 | .section.seealso div.seealso-content, .section.note div.note-content {
428 | display: block;
429 | margin-left: 6.5em;
430 | }
431 |
432 | .section.imports ul {
433 | margin: 0;
434 | list-style-type: none;
435 | padding-left: 1.5em;
436 |
437 | -moz-column-count: 4;
438 | -moz-column-gap: 20px;
439 | -webkit-column-count: 4;
440 | -webkit-column-gap: 20px;
441 | column-count: 4;
442 | column-gap: 20px;
443 | }
444 |
445 | @media only screen and (max-width: 1400px)
446 | {
447 | .section.imports ul {
448 | -moz-column-count: 3;
449 | -moz-column-gap: 20px;
450 | -webkit-column-count: 3;
451 | -webkit-column-gap: 20px;
452 | column-count: 3;
453 | column-gap: 20px;
454 | }
455 | }
456 |
457 | @media only screen and (max-width: 1100px)
458 | {
459 | .section.imports ul {
460 | -moz-column-count: 2;
461 | -moz-column-gap: 13px;
462 | -webkit-column-count: 2;
463 | -webkit-column-gap: 13px;
464 | column-count: 2;
465 | column-gap: 13px;
466 | }
467 | }
468 |
469 | @media only screen and (max-width: 800px)
470 | {
471 | .section.imports ul {
472 | -moz-column-count: 1;
473 | -moz-column-gap: 7px;
474 | -webkit-column-count: 1;
475 | -webkit-column-gap: 7px;
476 | column-count: 1;
477 | column-gap: 7px;
478 | }
479 | }
480 |
481 |
482 | .section.imports ul a {
483 | color: #111;
484 | }
485 |
486 |
487 | .section.seealso *:first-child, .section.note *:first-child {
488 | margin-top: 0em;
489 | }
490 |
491 | .section.seealso ul, .section.note ul {
492 | padding-left: 1.5em;
493 | }
494 |
495 | .section.seealso *:last-child, .section.note *:last-child {
496 | margin-bottom: 0em;
497 | }
498 |
499 | /**** FOOTER ****/
500 |
501 | footer
502 | {
503 | text-align: center;
504 | font-size: 60%;
505 | color: white;
506 | background-color: #333;
507 | }
508 |
509 | footer a
510 | {
511 | color: white;
512 | }
513 |
514 |
515 |
516 | /**** CODE ****/
517 |
518 | pre {
519 | margin-top: 0.4em;
520 | }
521 |
522 | /* DDoc code examples */
523 | code {
524 | background-color: #333;
525 | color: #eee;
526 | padding: 0.8em;
527 | border-radius: .1em;
528 | display: block;
529 | }
530 |
531 | code a {
532 | color: white;
533 | text-decoration: none;
534 | border-bottom: 1px dotted #888;
535 | }
536 |
537 | /* hmod/libddoc errors */
538 | div.error {
539 | color: darkred;
540 | }
541 |
542 | /* Markdown inline code and $(D code) */
543 | code.prettyprint, .d_inlinecode {
544 | font-family: monospace;
545 | color: #333;
546 | background-color:rgba(0,0,0,0.04);
547 | border-radius: .15em;
548 | border: 1px solid #C0C0C0;
549 | padding: 0.22em;
550 | display: inline;
551 | }
552 |
553 | code.prettyprint a {
554 | color: black;
555 | border-color: #777;
556 | }
557 |
558 | /*do not affect the first , which is not in a section*/
559 | div.section pre > code {
560 | margin: .5em;
561 | border-radius: .1em;
562 | padding: 0.8em;
563 | }
564 |
565 | div.section td pre {
566 | margin: 0;
567 | padding: 0;
568 | }
569 |
570 |
571 | div.section td code:not(.prettyprint) {
572 | margin: 0;
573 | padding: 0.6em;
574 | }
575 |
576 | .hljs {
577 | display: block; padding: 1em;
578 | background: #282B2E;
579 | overflow-x: auto;
580 | display: block;
581 | }
582 |
583 | .hljs-keyword,
584 | .hljs-literal,
585 | .hljs-change,
586 | .hljs-winutils,
587 | .hljs-flow,
588 | .lisp .hljs-title,
589 | .clojure .hljs-built_in,
590 | .nginx .hljs-title,
591 | .css .hljs-id,
592 | .tex .hljs-special {
593 | color: #93C763;
594 | }
595 |
596 | .hljs-number {
597 | color: #FFCD22;
598 | }
599 |
600 | .hljs {
601 | color: #E0E2E4;
602 | }
603 |
604 | .css .hljs-tag,
605 | .css .hljs-pseudo {
606 | color: #D0D2B5;
607 | }
608 |
609 | .hljs-attribute,
610 | .hljs .hljs-constant {
611 | color: #668BB0;
612 | }
613 |
614 | .xml .hljs-attribute {
615 | color: #B3B689;
616 | }
617 |
618 | .xml .hljs-tag .hljs-value {
619 | color: #E8E2B7;
620 | }
621 |
622 | .hljs-code,
623 | .hljs-class .hljs-title,
624 | .hljs-header {
625 | color: white;
626 | }
627 |
628 | .hljs-class,
629 | .hljs-hexcolor {
630 | color: #93C763;
631 | }
632 |
633 | .hljs-regexp {
634 | color: #D39745;
635 | }
636 |
637 | .hljs-at_rule,
638 | .hljs-at_rule .hljs-keyword {
639 | color: #A082BD;
640 | }
641 |
642 | .hljs-doctype {
643 | color: #557182;
644 | }
645 |
646 | .hljs-link_url,
647 | .hljs-tag,
648 | .hljs-tag .hljs-title,
649 | .hljs-bullet,
650 | .hljs-subst,
651 | .hljs-emphasis,
652 | .haskell .hljs-type,
653 | .hljs-preprocessor,
654 | .hljs-pragma,
655 | .ruby .hljs-class .hljs-parent,
656 | .hljs-built_in,
657 | .sql .hljs-aggregate,
658 | .django .hljs-template_tag,
659 | .django .hljs-variable,
660 | .smalltalk .hljs-class,
661 | .hljs-javadoc,
662 | .django .hljs-filter .hljs-argument,
663 | .smalltalk .hljs-localvars,
664 | .smalltalk .hljs-array,
665 | .hljs-attr_selector,
666 | .hljs-pseudo,
667 | .hljs-addition,
668 | .hljs-stream,
669 | .hljs-envvar,
670 | .apache .hljs-tag,
671 | .apache .hljs-cbracket,
672 | .tex .hljs-command,
673 | .hljs-prompt {
674 | color: #8CBBAD;
675 | }
676 |
677 | .hljs-string {
678 | color: #EC7600;
679 | }
680 |
681 | .hljs-comment,
682 | .java .hljs-annotation,
683 | .hljs-blockquote,
684 | .hljs-horizontal_rule,
685 | .python .hljs-decorator,
686 | .hljs-template_comment,
687 | .hljs-pi,
688 | .hljs-deletion,
689 | .hljs-shebang,
690 | .apache .hljs-sqbracket,
691 | .tex .hljs-formula {
692 | color: #818E96;
693 | }
694 |
695 | .hljs-keyword,
696 | .hljs-literal,
697 | .css .hljs-id,
698 | .hljs-phpdoc,
699 | .hljs-title,
700 | .hljs-header,
701 | .haskell .hljs-type,
702 | .vbscript .hljs-built_in,
703 | .sql .hljs-aggregate,
704 | .rsl .hljs-built_in,
705 | .smalltalk .hljs-class,
706 | .diff .hljs-header,
707 | .hljs-chunk,
708 | .hljs-winutils,
709 | .bash .hljs-variable,
710 | .apache .hljs-tag,
711 | .tex .hljs-special,
712 | .hljs-request,
713 | .hljs-at_rule .hljs-keyword,
714 | .hljs-status {
715 | font-weight: bold;
716 | }
717 |
718 | .coffeescript .javascript,
719 | .javascript .xml,
720 | .tex .hljs-formula,
721 | .xml .javascript,
722 | .xml .vbscript,
723 | .xml .css,
724 | .xml .hljs-cdata {
725 | opacity: 0.5;
726 | }
727 |
--------------------------------------------------------------------------------
/doc/tinyendian.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | tinyendian
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
⌂
17 |
tinyendian
18 |
19 |
28 |
29 |
public @system pure nothrow @nogc void swapByteOrder (T)(T[] array)
30 | if([2, 4].canFind(T.sizeof))
31 |
32 |
Swap byte order of items in an array in place.
33 |
34 |
35 |
36 |
37 |
Parameters
38 |
39 | T Item type. Must be either 2 or 4 bytes long.
40 |
41 |
42 | array Buffer with values to fix byte order of.
43 |
44 |
45 |
46 |
47 |
public @system pure nothrow @nogc auto fixUTFByteOrder (ubyte [] array)
48 |
49 |
Convert byte order of an array encoded in UTF(8/16/32) to system endianness in place.
50 |
51 |
52 |
53 |
54 |
Uses the UTF byte-order-mark (BOM) to determine UTF encoding. If there is no BOM
55 | at the beginning of array, UTF-8 is assumed (this is compatible with ASCII). The
56 | BOM, if any, will be removed from the buffer.
57 |
58 |
If the encoding is determined to be UTF-16 or UTF-32 and there aren't enough bytes
59 | for the last code unit (i.e. if array.length is odd for UTF-16 or not divisible by
60 | 4 for UTF-32), the extra bytes (1 for UTF-16, 1-3 for UTF-32) are stripped.
61 |
62 |
Note that this function does not check if the array is a valid UTF string. It
63 | only works with the BOM and 1,2 or 4-byte items.
64 |
65 |
66 |
67 |
68 |
Parameters
69 |
70 | array The array with UTF-data.
71 |
72 |
73 |
74 |
75 |
Returns
76 |
A struct with the following members:
77 |
78 |
ubyte[] array
A slice of the input array containing data in correct
79 | byte order, without BOM and in case of UTF-16/UTF-32,
80 | without stripped bytes, if any.
81 | UTFEncoding encoding
Encoding of the result (UTF-8, UTF-16 or UTF-32)
82 | std.system.Endian endian
Endianness of the original array.
83 | uint bytesStripped
Number of bytes stripped from a UTF-16/UTF-32 array, if
84 | any. This is non-zero only if array.length was not
85 | divisible by 2 or 4 for UTF-16 and UTF-32, respectively.
86 |
87 |
88 |
89 |
90 |
Complexity
91 |
(BIGOH array.length)
92 |
93 |
94 |
95 |
96 |
A minimal library providing functionality for changing the endianness of data.
97 |
98 |
99 |
100 |
101 |
Enums Functions swapByteOrder Swap byte order of items in an array in place.
104 |
105 | fixUTFByteOrder Convert byte order of an array encoded in UTF(8/16/32) to system endianness in place.
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/doc/tinyendian/UTFEncoding.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | UTFEncoding
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
28 |
29 |
public enum UTFEncoding : ubyte
30 |
31 |
Unicode UTF encodings.
32 |
33 |
34 |
35 |
36 |
38 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/dub.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tinyendian",
3 | "description": "Lightweight endianness handling library",
4 | "authors": [ "Ferdinand Majerech" ],
5 | "importPaths": ["source"],
6 | "license": "Boost 1.0",
7 | "homepage": "https://github.com/kiith-sa/tinyendian",
8 | "copyright": "Copyright © 2014, Ferdinand Majerech",
9 |
10 | "buildTypes":
11 | {
12 | "debug": { "buildOptions": ["debugMode", "debugInfoC"] },
13 | "release": { "buildOptions": ["releaseMode", "optimize", "inline", "noBoundsCheck"] },
14 | "profile": { "buildOptions": ["releaseMode", "optimize", "noBoundsCheck", "debugInfoC"] },
15 | },
16 | }
17 |
--------------------------------------------------------------------------------
/hmod.cfg:
--------------------------------------------------------------------------------
1 | # This file contains configuration options for harbored-mod (hmod).
2 | #
3 | # By default, hmod loads configuration from file 'hmod.cfg' in the directory from where
4 | # hmod is running, if such file exists. These configuration options can also be passed
5 | # as command-line options for hmod, overriding contents of the config file, if any,
6 | # with the exception of options that allow multiple values (such as 'exclude' or
7 | # 'macros') where the values specified as command-line options are *added* to the values
8 | # in config file.
9 |
10 |
11 |
12 | # Source code files or directories to document. Specify more than once to document more
13 | # files/directories, e.g:
14 | #
15 | # source = ./source
16 | # source = ./thirdparty
17 | #
18 | # This will document both the source code in the ./source/ and ./thirdparty/ directories.
19 | #
20 | # For DUB (http://code.dlang.org) projects, './source' is usually a good setting here.
21 | source = ./source
22 |
23 |
24 | # Name of the project. Used on the main page and possibly other places to help identify
25 | # the project.
26 | project-name = tinyendian
27 |
28 |
29 | # Version of the project. Used on the main page and possibly other places to help
30 | # identify the project.
31 | project-version =
32 |
33 |
34 | # Set to true to disable Markdown support, so that only DDoc is used.
35 | no-markdown = false
36 |
37 |
38 | # Directory where the generated documentation will be written.
39 | output-directory = ./doc
40 |
41 | # Output format. Supported values:
42 | # html-simple
43 | # Every function, variable, etc. will be documented in a separate
44 | # HTML file. A documentation page of an aggregate (e.g. class) will
45 | # link to these files. Generates a large number of files; not
46 | # recommended for large projects.
47 | # html-aggregated
48 | # Members of an aggregate will be documented in the same file as the
49 | # aggregate, unless they are aggregates themselves. That is, member
50 | # functions or variables will be documented in the same file as the
51 | # class that contains them, but a subclass will be documented in a
52 | # separate file.
53 | format = html-aggregated
54 |
55 |
56 | # Modules or packages to exclude from generated documentation. Specify more than once to
57 | # exclude more modules/packages, e.g:
58 | #
59 | # exclude = tharsis.util
60 | # exclude = tharsis.entity.gamestate
61 | #
62 | # This will exclude both the package (or module) tharsis.util and module (or package)
63 | # tharsis.entity.gamestate .
64 |
65 | exclude =
66 |
67 |
68 | # DDoc+markdown source of the main page of your documentation. Currently the main page is
69 | # blank by default; this can be used to fill it with something useful.
70 |
71 | index =
72 |
73 |
74 | # Filename of DDoc+markdown source of additional content to add to the table of contents
75 | # sidebar. Useful e.g. to add links to tutorials. Can be used more than once to add
76 | # content from more files.
77 |
78 | toc-additional =
79 |
80 |
81 | # CSS file to use for styling. Can be used to replace the default style.
82 | # To create a new style, you can start by generating the default style file with
83 | # 'hmod --generate-css CSS_OUT_FILE' (CSS_OUT_FILE is name the generated file will have)
84 | # and then modifying the CSS to get the desired style.
85 |
86 | css =
87 |
88 |
89 | # File to load DDoc macros from. Can be used to override builtin macros or add new ones.
90 | # Can be specified more than once to use multiple macro files, e.g.:
91 | #
92 | # macros = macros.ddoc
93 | # macros = moremacros.ddoc
94 |
95 | macros =
96 |
97 |
98 | # Maximum file size of D modules harbored-mod will process, in kiB. Any file
99 | # bigger than specified size will be ignored. Useful in rare cases when modules
100 | # are huge enough that the parser spends too much memory.
101 | # By default, we ignore modules bigger than 16MiB.
102 |
103 | max-file-size = 16384
104 |
105 |
106 | # Additional config file to load, if needed. Configuration options in specified file will
107 | # override or add to any options specified before this line, and will be overridden by
108 | # any options after this line. Think of it as including the config file in this file.
109 |
110 | config =
111 |
112 |
113 |
114 | #---------------------------------------------------------------------------
115 | # Configuration options **only** useful for harbored-mod testing
116 | #---------------------------------------------------------------------------
117 | # Uncommenting these will result in printing help information; only useful for testing.
118 | #
119 | # # Print help message.
120 | #
121 | # help = true
122 | #
123 | #
124 | # # Generate default CSS file and write it to specified file.
125 | # generate-css = hmod-style.css
126 | #
127 | #
128 | # # Generate default config file and write it to 'hmod.cfg'.
129 | #
130 | # generate-cfg = true
131 |
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | # -*- mode: python; -*-
2 |
3 | project(
4 | 'tinyendian',
5 | 'd',
6 | meson_version: '>=0.41',
7 | version: '0.2.0',
8 | default_options: ['buildtype=release'],
9 | )
10 |
11 | src_dir = include_directories('source/')
12 | pkgc = import('pkgconfig')
13 |
14 | tinyendian_src = [
15 | 'source/tinyendian.d'
16 | ]
17 |
18 | install_headers(tinyendian_src, subdir: 'd/')
19 |
20 | tinyendian_lib = library(
21 | meson.project_name(),
22 | [tinyendian_src],
23 | include_directories: [src_dir],
24 | version: meson.project_version(),
25 | pic: true,
26 | install: true,
27 | )
28 |
29 | pkgc.generate(
30 | name: meson.project_name(),
31 | libraries: tinyendian_lib,
32 | subdirs: 'd/',
33 | version: meson.project_version(),
34 | description: 'Lightweight endianness library for D.'
35 | )
36 |
37 | # Make Tinyendian easy to use as subproject
38 | tinyendian_dep = declare_dependency(
39 | link_with: tinyendian_lib,
40 | include_directories: [src_dir]
41 | )
42 |
--------------------------------------------------------------------------------
/source/tinyendian.d:
--------------------------------------------------------------------------------
1 | // Copyright Ferdinand Majerech 2014.
2 | // Distributed under the Boost Software License, Version 1.0.
3 | // (See accompanying file LICENSE_1_0.txt or copy at
4 | // http://www.boost.org/LICENSE_1_0.txt)
5 |
6 | /// A minimal library providing functionality for changing the endianness of data.
7 | module tinyendian;
8 |
9 | import std.system : Endian, endian;
10 |
11 | /// Unicode UTF encodings.
12 | enum UTFEncoding : ubyte
13 | {
14 | UTF_8,
15 | UTF_16,
16 | UTF_32
17 | }
18 | ///
19 | @safe unittest
20 | {
21 | const ints = [314, -101];
22 | int[2] intsSwapBuffer = ints;
23 | swapByteOrder(intsSwapBuffer[]);
24 | swapByteOrder(intsSwapBuffer[]);
25 | assert(ints == intsSwapBuffer, "Lost information when swapping byte order");
26 |
27 | const floats = [3.14f, 10.1f];
28 | float[2] floatsSwapBuffer = floats;
29 | swapByteOrder(floatsSwapBuffer[]);
30 | swapByteOrder(floatsSwapBuffer[]);
31 | assert(floats == floatsSwapBuffer, "Lost information when swapping byte order");
32 | }
33 |
34 | /** Swap byte order of items in an array in place.
35 | *
36 | * Params:
37 | *
38 | * T = Item type. Must be either 2 or 4 bytes long.
39 | * array = Buffer with values to fix byte order of.
40 | */
41 | void swapByteOrder(T)(T[] array) @trusted @nogc pure nothrow
42 | if (T.sizeof == 2 || T.sizeof == 4)
43 | {
44 | // Swap the byte order of all read characters.
45 | foreach (ref item; array)
46 | {
47 | static if (T.sizeof == 2)
48 | {
49 | import std.algorithm.mutation : swap;
50 | swap(*cast(ubyte*)&item, *(cast(ubyte*)&item + 1));
51 | }
52 | else static if (T.sizeof == 4)
53 | {
54 | import core.bitop : bswap;
55 | const swapped = bswap(*cast(uint*)&item);
56 | item = *cast(const(T)*)&swapped;
57 | }
58 | else static assert(false, "Unsupported T: " ~ T.stringof);
59 | }
60 | }
61 |
62 | /// See fixUTFByteOrder.
63 | struct FixUTFByteOrderResult
64 | {
65 | ubyte[] array;
66 | UTFEncoding encoding;
67 | Endian endian;
68 | uint bytesStripped = 0;
69 | }
70 |
71 | /** Convert byte order of an array encoded in UTF(8/16/32) to system endianness in place.
72 | *
73 | * Uses the UTF byte-order-mark (BOM) to determine UTF encoding. If there is no BOM
74 | * at the beginning of array, UTF-8 is assumed (this is compatible with ASCII). The
75 | * BOM, if any, will be removed from the buffer.
76 | *
77 | * If the encoding is determined to be UTF-16 or UTF-32 and there aren't enough bytes
78 | * for the last code unit (i.e. if array.length is odd for UTF-16 or not divisible by
79 | * 4 for UTF-32), the extra bytes (1 for UTF-16, 1-3 for UTF-32) are stripped.
80 | *
81 | * Note that this function does $(B not) check if the array is a valid UTF string. It
82 | * only works with the BOM and 1,2 or 4-byte items.
83 | *
84 | * Params:
85 | *
86 | * array = The array with UTF-data.
87 | *
88 | * Returns:
89 | *
90 | * A struct with the following members:
91 | *
92 | * $(D ubyte[] array) A slice of the input array containing data in correct
93 | * byte order, without BOM and in case of UTF-16/UTF-32,
94 | * without stripped bytes, if any.
95 | * $(D UTFEncoding encoding) Encoding of the result (UTF-8, UTF-16 or UTF-32)
96 | * $(D std.system.Endian endian) Endianness of the original array.
97 | * $(D uint bytesStripped) Number of bytes stripped from a UTF-16/UTF-32 array, if
98 | * any. This is non-zero only if array.length was not
99 | * divisible by 2 or 4 for UTF-16 and UTF-32, respectively.
100 | *
101 | * Complexity: (BIGOH array.length)
102 | */
103 | auto fixUTFByteOrder(ubyte[] array) @safe @nogc pure nothrow
104 | {
105 | // Enumerates UTF BOMs, matching indices to byteOrderMarks/bomEndian.
106 | enum BOM: ubyte
107 | {
108 | UTF_8 = 0,
109 | UTF_16_LE = 1,
110 | UTF_16_BE = 2,
111 | UTF_32_LE = 3,
112 | UTF_32_BE = 4,
113 | None = ubyte.max
114 | }
115 |
116 | // These 2 are from std.stream
117 | static immutable ubyte[][5] byteOrderMarks = [ [0xEF, 0xBB, 0xBF],
118 | [0xFF, 0xFE],
119 | [0xFE, 0xFF],
120 | [0xFF, 0xFE, 0x00, 0x00],
121 | [0x00, 0x00, 0xFE, 0xFF] ];
122 | static immutable Endian[5] bomEndian = [ endian,
123 | Endian.littleEndian,
124 | Endian.bigEndian,
125 | Endian.littleEndian,
126 | Endian.bigEndian ];
127 |
128 | // Documented in function ddoc.
129 |
130 | FixUTFByteOrderResult result;
131 |
132 | // Detect BOM, if any, in the bytes we've read. -1 means no BOM.
133 | // Need the last match: First 2 bytes of UTF-32LE BOM match the UTF-16LE BOM. If we
134 | // used the first match, UTF-16LE would be detected when we have a UTF-32LE BOM.
135 | import std.algorithm.searching : startsWith;
136 | BOM bomId = BOM.None;
137 | foreach (i, bom; byteOrderMarks)
138 | if (array.startsWith(bom))
139 | bomId = cast(BOM)i;
140 |
141 | result.endian = (bomId != BOM.None) ? bomEndian[bomId] : Endian.init;
142 |
143 | // Start of UTF data (after BOM, if any)
144 | size_t start = 0;
145 | // If we've read more than just the BOM, put the rest into the array.
146 | with(BOM) final switch(bomId)
147 | {
148 | case None: result.encoding = UTFEncoding.UTF_8; break;
149 | case UTF_8:
150 | start = 3;
151 | result.encoding = UTFEncoding.UTF_8;
152 | break;
153 | case UTF_16_LE, UTF_16_BE:
154 | result.bytesStripped = array.length % 2;
155 | start = 2;
156 | result.encoding = UTFEncoding.UTF_16;
157 | break;
158 | case UTF_32_LE, UTF_32_BE:
159 | result.bytesStripped = array.length % 4;
160 | start = 4;
161 | result.encoding = UTFEncoding.UTF_32;
162 | break;
163 | }
164 |
165 | // If there's a BOM, we need to move data back to ensure it starts at array[0]
166 | if (start != 0)
167 | {
168 | array = array[start .. $ - result.bytesStripped];
169 | }
170 |
171 | // We enforce above that array.length is divisible by 2/4 for UTF-16/32
172 | if (endian != result.endian)
173 | {
174 | if (result.encoding == UTFEncoding.UTF_16)
175 | swapByteOrder(cast(wchar[])array);
176 | else if (result.encoding == UTFEncoding.UTF_32)
177 | swapByteOrder(cast(dchar[])array);
178 | }
179 |
180 | result.array = array;
181 | return result;
182 | }
183 | ///
184 | @safe unittest
185 | {
186 | {
187 | ubyte[] s = [0xEF, 0xBB, 0xBF, 'a'];
188 | FixUTFByteOrderResult r = fixUTFByteOrder(s);
189 | assert(r.encoding == UTFEncoding.UTF_8);
190 | assert(r.array.length == 1);
191 | assert(r.array == ['a']);
192 | assert(r.endian == Endian.littleEndian);
193 | }
194 |
195 | {
196 | ubyte[] s = ['a'];
197 | FixUTFByteOrderResult r = fixUTFByteOrder(s);
198 | assert(r.encoding == UTFEncoding.UTF_8);
199 | assert(r.array.length == 1);
200 | assert(r.array == ['a']);
201 | assert(r.endian == Endian.bigEndian);
202 | }
203 |
204 | {
205 | // strip 'a' b/c not complete unit
206 | ubyte[] s = [0xFE, 0xFF, 'a'];
207 | FixUTFByteOrderResult r = fixUTFByteOrder(s);
208 | assert(r.encoding == UTFEncoding.UTF_16);
209 | assert(r.array.length == 0);
210 | assert(r.endian == Endian.bigEndian);
211 | }
212 |
213 | }
214 |
--------------------------------------------------------------------------------