Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. The Weird and The Wonderful
  4. Blessed endian mismatches collide with progress

Blessed endian mismatches collide with progress

Scheduled Pinned Locked Moved The Weird and The Wonderful
designc++csscomgraphics
13 Posts 7 Posters 20 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    honey the codewitch
    wrote on last edited by
    #1

    Almost all embedded MCUs are little endian. Almost all display controllers that can connect to them are big endian. My graphics library builds pixels in big endian order on little endian machines as a consequence. It's just more efficient. LVGL is another embedded graphics library - one I contribute to - and they removed a feature on version 9+ where you could set it to swap the bytes on a 16 bit color value. This is to compensate for the endian issues. Not swapping during the draw operation means you need to scan and rearrange the transfer buffer before you send it to the display.

    evoid lcd_flush_display( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map) {
    size_t count = (area->x2-area->x1+1)*(area->y2-area->y1+1);
    for(int i = 0;i>8)&0xFF);
    }
    esp_lcd_panel_draw_bitmap(lcd_handle,area->x1,area->y1,area->x2+1,area->y2+1,px_map);
    LV_UNUSED(disp);
    }

    This is less efficient. It's also ugly. This is what's for dinner now in LVGL. This is "progress". The worst part is I understand and even sort of agree with why they did it. The issue is multiple displays, and the fact that some displays may not need the swap, perhaps because they're monochrome or something. Previously prior to 8 LVGL simply didn't support that scenario because the swap option was a #define (LVGL is C, not C++) and it applied to all displays as a consequence. But to remove it entirely seems like it was a decision guided by expediency more than anything. It's unfortunate. And all of it reminds me of why I hate the fact that humans couldn't universally agree on endian order.

    Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

    R P T J 4 Replies Last reply
    0
    • H honey the codewitch

      Almost all embedded MCUs are little endian. Almost all display controllers that can connect to them are big endian. My graphics library builds pixels in big endian order on little endian machines as a consequence. It's just more efficient. LVGL is another embedded graphics library - one I contribute to - and they removed a feature on version 9+ where you could set it to swap the bytes on a 16 bit color value. This is to compensate for the endian issues. Not swapping during the draw operation means you need to scan and rearrange the transfer buffer before you send it to the display.

      evoid lcd_flush_display( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map) {
      size_t count = (area->x2-area->x1+1)*(area->y2-area->y1+1);
      for(int i = 0;i>8)&0xFF);
      }
      esp_lcd_panel_draw_bitmap(lcd_handle,area->x1,area->y1,area->x2+1,area->y2+1,px_map);
      LV_UNUSED(disp);
      }

      This is less efficient. It's also ugly. This is what's for dinner now in LVGL. This is "progress". The worst part is I understand and even sort of agree with why they did it. The issue is multiple displays, and the fact that some displays may not need the swap, perhaps because they're monochrome or something. Previously prior to 8 LVGL simply didn't support that scenario because the swap option was a #define (LVGL is C, not C++) and it applied to all displays as a consequence. But to remove it entirely seems like it was a decision guided by expediency more than anything. It's unfortunate. And all of it reminds me of why I hate the fact that humans couldn't universally agree on endian order.

      Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

      R Offline
      R Offline
      Ron Anders
      wrote on last edited by
      #2

      One little two little three lit....

      1 Reply Last reply
      0
      • H honey the codewitch

        Almost all embedded MCUs are little endian. Almost all display controllers that can connect to them are big endian. My graphics library builds pixels in big endian order on little endian machines as a consequence. It's just more efficient. LVGL is another embedded graphics library - one I contribute to - and they removed a feature on version 9+ where you could set it to swap the bytes on a 16 bit color value. This is to compensate for the endian issues. Not swapping during the draw operation means you need to scan and rearrange the transfer buffer before you send it to the display.

        evoid lcd_flush_display( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map) {
        size_t count = (area->x2-area->x1+1)*(area->y2-area->y1+1);
        for(int i = 0;i>8)&0xFF);
        }
        esp_lcd_panel_draw_bitmap(lcd_handle,area->x1,area->y1,area->x2+1,area->y2+1,px_map);
        LV_UNUSED(disp);
        }

        This is less efficient. It's also ugly. This is what's for dinner now in LVGL. This is "progress". The worst part is I understand and even sort of agree with why they did it. The issue is multiple displays, and the fact that some displays may not need the swap, perhaps because they're monochrome or something. Previously prior to 8 LVGL simply didn't support that scenario because the swap option was a #define (LVGL is C, not C++) and it applied to all displays as a consequence. But to remove it entirely seems like it was a decision guided by expediency more than anything. It's unfortunate. And all of it reminds me of why I hate the fact that humans couldn't universally agree on endian order.

        Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

        P Offline
        P Offline
        PIEBALDconsult
        wrote on last edited by
        #3

        My wife is little-endian...

        1 Reply Last reply
        0
        • H honey the codewitch

          Almost all embedded MCUs are little endian. Almost all display controllers that can connect to them are big endian. My graphics library builds pixels in big endian order on little endian machines as a consequence. It's just more efficient. LVGL is another embedded graphics library - one I contribute to - and they removed a feature on version 9+ where you could set it to swap the bytes on a 16 bit color value. This is to compensate for the endian issues. Not swapping during the draw operation means you need to scan and rearrange the transfer buffer before you send it to the display.

          evoid lcd_flush_display( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map) {
          size_t count = (area->x2-area->x1+1)*(area->y2-area->y1+1);
          for(int i = 0;i>8)&0xFF);
          }
          esp_lcd_panel_draw_bitmap(lcd_handle,area->x1,area->y1,area->x2+1,area->y2+1,px_map);
          LV_UNUSED(disp);
          }

          This is less efficient. It's also ugly. This is what's for dinner now in LVGL. This is "progress". The worst part is I understand and even sort of agree with why they did it. The issue is multiple displays, and the fact that some displays may not need the swap, perhaps because they're monochrome or something. Previously prior to 8 LVGL simply didn't support that scenario because the swap option was a #define (LVGL is C, not C++) and it applied to all displays as a consequence. But to remove it entirely seems like it was a decision guided by expediency more than anything. It's unfortunate. And all of it reminds me of why I hate the fact that humans couldn't universally agree on endian order.

          Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

          T Offline
          T Offline
          trønderen
          wrote on last edited by
          #4

          So which way would you want it? The little endian way we write email addresses and domain names? Or the big endian way we write IP addresses? The little endian way we write snail mail addresses on an envelope? Or the big endian way we dial a phone number? The little endian way we sign a document with our full name? Or the big endian way we are listed in the telephone book? (Iceland is an exception - the phone book is little endian!) The big endian way we write multi-digit Arabic numerals? Or the big endian (?) way Arabs write multi-digit numerals? They reading right-to-left, so to them, it is little endian. The big endian way Americans write month/date, or the little endian way they write month/date - year? The little endian way street addresses are written by American standards (17 Main street) or the big endian way used e.g. in Norway (Storgata 17)? The big endian way when adding an entrance (17 Main Street, Entrance B) or stick to a consistent little endian way (Entrance B 17 Main Street)? Four-and-twenty blackbirds baked in a pie, or Twenty four blackbirds baked in a pie? A quarter past nine, or nine fifteen? If you want the entire world to agree on a single endianness, you probably have to work yourself up to a position of an almighty ruler of the world. Even if you got in a position where you could turn the other way IP addresses, and put the area code at the end of the phone number, and reorder the phone book on first names rather than last, and teach schoolkids to write the tens after the ones and then the hundreds and the thousands, and making all Americans write the date before the month, and ... What would you do with IBM mainframes? With systems based on MC68, 8051 or OpenRISC, older Power and SPARC systems? Would you make them illegal? There are some small, insignificant embedded (and other) architectures that allow memory access in either endianness, such as ARM, newer Power or SPARC, Alpha, MIPS, i860 and PA-RISC. You may consider them all to be so unimportant that you will ignore them. You may also find unimportant CPU instructions for reversing the byte order in halfwords, words or doublewords, provided by several architectures of one (or one preferred) endianness. I guess you will be following up here at WeirdAndWonderful/Feature/com.codeproject.www//:http

          Religious freedom is the freedom to say that two plus two make five.

          H 1 Reply Last reply
          0
          • T trønderen

            So which way would you want it? The little endian way we write email addresses and domain names? Or the big endian way we write IP addresses? The little endian way we write snail mail addresses on an envelope? Or the big endian way we dial a phone number? The little endian way we sign a document with our full name? Or the big endian way we are listed in the telephone book? (Iceland is an exception - the phone book is little endian!) The big endian way we write multi-digit Arabic numerals? Or the big endian (?) way Arabs write multi-digit numerals? They reading right-to-left, so to them, it is little endian. The big endian way Americans write month/date, or the little endian way they write month/date - year? The little endian way street addresses are written by American standards (17 Main street) or the big endian way used e.g. in Norway (Storgata 17)? The big endian way when adding an entrance (17 Main Street, Entrance B) or stick to a consistent little endian way (Entrance B 17 Main Street)? Four-and-twenty blackbirds baked in a pie, or Twenty four blackbirds baked in a pie? A quarter past nine, or nine fifteen? If you want the entire world to agree on a single endianness, you probably have to work yourself up to a position of an almighty ruler of the world. Even if you got in a position where you could turn the other way IP addresses, and put the area code at the end of the phone number, and reorder the phone book on first names rather than last, and teach schoolkids to write the tens after the ones and then the hundreds and the thousands, and making all Americans write the date before the month, and ... What would you do with IBM mainframes? With systems based on MC68, 8051 or OpenRISC, older Power and SPARC systems? Would you make them illegal? There are some small, insignificant embedded (and other) architectures that allow memory access in either endianness, such as ARM, newer Power or SPARC, Alpha, MIPS, i860 and PA-RISC. You may consider them all to be so unimportant that you will ignore them. You may also find unimportant CPU instructions for reversing the byte order in halfwords, words or doublewords, provided by several architectures of one (or one preferred) endianness. I guess you will be following up here at WeirdAndWonderful/Feature/com.codeproject.www//:http

            Religious freedom is the freedom to say that two plus two make five.

            H Offline
            H Offline
            honey the codewitch
            wrote on last edited by
            #5

            Frankly, little endian everything, if I had my way, but it's too late. The internet is big endian for example. I don't know what you're talking about in terms of writing email addresses and domain names. I'm talking about byte order of machine words. That's all.

            Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

            T 1 Reply Last reply
            0
            • H honey the codewitch

              Frankly, little endian everything, if I had my way, but it's too late. The internet is big endian for example. I don't know what you're talking about in terms of writing email addresses and domain names. I'm talking about byte order of machine words. That's all.

              Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

              T Offline
              T Offline
              trønderen
              wrote on last edited by
              #6

              honey the codewitch wrote:

              I don't know what you're talking about in terms of writing email addresses and domain names.

              What goes first, to the left: The smallest unit, i.e. the individual recipient, or the larger unit comprising a huge number of them, the mail server name? Which goes first: The smaller subdomain 'codeproject' or the TLD 'com'? Are you really sure that the internet is consistently big endian? IP addresses certainly are, but is that all that there is? (Then let's keep dancing ...) Curious memory: The very first map I saw of the internet, the nodes were labeled with a number, mostly 3-digit. Several of the nodes had the same number. I had to have these labels explained to me: It was IBM 360 mainframe model provided at that site as the main computing resource. IBM mainframes always were big endian. That might explain why IP addresses were selected to be big endian. If you go for consistent little endian format: Do you consider the last character in a name to be the most significant? If memory contains the bytes, at increasing addresses, 'J', 'O', 'H', 'N', would you then consider 'J' the least significant one, e.g. if you were to sort a list of names? Would you rather choose to store 'JOHN' as 'N', 'H', 'O', 'J'? Would you then require all names (or other strings) to be of a fixed length, with the characters to be compared for sorting at the same offset from the start of the string? Or would you construct a descriptor for each string, each with an index (offset) starting at the last character, decrementing it as the sorting progressed to less significant characters? Or would you store numeric values as little endian, but strings as big endian? Bottom line: It isn't as simple as 'Choose one and always use that'. You can't define yourself away from endianness problems, even if you have omnipotent power. Unless, of course, if your power is so omnipotent that you can define two plus two to make something else than four.

              Religious freedom is the freedom to say that two plus two make five.

              H 1 2 Replies Last reply
              0
              • T trønderen

                honey the codewitch wrote:

                I don't know what you're talking about in terms of writing email addresses and domain names.

                What goes first, to the left: The smallest unit, i.e. the individual recipient, or the larger unit comprising a huge number of them, the mail server name? Which goes first: The smaller subdomain 'codeproject' or the TLD 'com'? Are you really sure that the internet is consistently big endian? IP addresses certainly are, but is that all that there is? (Then let's keep dancing ...) Curious memory: The very first map I saw of the internet, the nodes were labeled with a number, mostly 3-digit. Several of the nodes had the same number. I had to have these labels explained to me: It was IBM 360 mainframe model provided at that site as the main computing resource. IBM mainframes always were big endian. That might explain why IP addresses were selected to be big endian. If you go for consistent little endian format: Do you consider the last character in a name to be the most significant? If memory contains the bytes, at increasing addresses, 'J', 'O', 'H', 'N', would you then consider 'J' the least significant one, e.g. if you were to sort a list of names? Would you rather choose to store 'JOHN' as 'N', 'H', 'O', 'J'? Would you then require all names (or other strings) to be of a fixed length, with the characters to be compared for sorting at the same offset from the start of the string? Or would you construct a descriptor for each string, each with an index (offset) starting at the last character, decrementing it as the sorting progressed to less significant characters? Or would you store numeric values as little endian, but strings as big endian? Bottom line: It isn't as simple as 'Choose one and always use that'. You can't define yourself away from endianness problems, even if you have omnipotent power. Unless, of course, if your power is so omnipotent that you can define two plus two to make something else than four.

                Religious freedom is the freedom to say that two plus two make five.

                H Offline
                H Offline
                honey the codewitch
                wrote on last edited by
                #7

                Generally, the Internet is big endian, as in any binary protocols that exist on the internet expect "Network Byte Order" which is big endian. I'm happy to be proven wrong on that score, but it applies to everything I can think of, be it 32 or 64 bit IP addresses, 16 bit port numbers, NTP, etc. I generally sort asciibetically if I'm sorting with a machine. I don't care about text in this instance. Like I said, I was only referring to machine word byte order.

                Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                T 1 Reply Last reply
                0
                • T trønderen

                  honey the codewitch wrote:

                  I don't know what you're talking about in terms of writing email addresses and domain names.

                  What goes first, to the left: The smallest unit, i.e. the individual recipient, or the larger unit comprising a huge number of them, the mail server name? Which goes first: The smaller subdomain 'codeproject' or the TLD 'com'? Are you really sure that the internet is consistently big endian? IP addresses certainly are, but is that all that there is? (Then let's keep dancing ...) Curious memory: The very first map I saw of the internet, the nodes were labeled with a number, mostly 3-digit. Several of the nodes had the same number. I had to have these labels explained to me: It was IBM 360 mainframe model provided at that site as the main computing resource. IBM mainframes always were big endian. That might explain why IP addresses were selected to be big endian. If you go for consistent little endian format: Do you consider the last character in a name to be the most significant? If memory contains the bytes, at increasing addresses, 'J', 'O', 'H', 'N', would you then consider 'J' the least significant one, e.g. if you were to sort a list of names? Would you rather choose to store 'JOHN' as 'N', 'H', 'O', 'J'? Would you then require all names (or other strings) to be of a fixed length, with the characters to be compared for sorting at the same offset from the start of the string? Or would you construct a descriptor for each string, each with an index (offset) starting at the last character, decrementing it as the sorting progressed to less significant characters? Or would you store numeric values as little endian, but strings as big endian? Bottom line: It isn't as simple as 'Choose one and always use that'. You can't define yourself away from endianness problems, even if you have omnipotent power. Unless, of course, if your power is so omnipotent that you can define two plus two to make something else than four.

                  Religious freedom is the freedom to say that two plus two make five.

                  1 Offline
                  1 Offline
                  11917640 Member
                  wrote on last edited by
                  #8

                  I like this approach: Let's decide, whether the whole world is little or big endian. Then we can apply this decision in the computer world. By the way, what programming language was used to write the whole world? I think this was C.

                  K 1 Reply Last reply
                  0
                  • H honey the codewitch

                    Generally, the Internet is big endian, as in any binary protocols that exist on the internet expect "Network Byte Order" which is big endian. I'm happy to be proven wrong on that score, but it applies to everything I can think of, be it 32 or 64 bit IP addresses, 16 bit port numbers, NTP, etc. I generally sort asciibetically if I'm sorting with a machine. I don't care about text in this instance. Like I said, I was only referring to machine word byte order.

                    Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                    T Offline
                    T Offline
                    trønderen
                    wrote on last edited by
                    #9

                    Sure, we could select one tiny little speck of the endianness problem - byte ordering, say - and ignore the rest. Assuming that it was possible to select one single byte ordering and rule out any others, we could declare: 'Hooray! Now the world is free of endianness problems!' Maybe that would be the case inside your little IDE. At least until you have to handle a date. Or an IP address. Or a decimal multi-digit number. You may argue: But those are not endianness problems! They is something different from the ordering of bytes within a word! I'll accept what you say, and you have the full right to say that nothing else than byte ordering falls in under 'endianness'. But the issues are about ordering smallest unit to biggest or biggest to smallest. We could use a different term for this wider problem area, e.g. 'big ordering' or 'small ordering' (and 'mixed ordering'), making 'endianness' a subset of 'ordering'. In principle, we could then throw out all IBMs, Powers, MC68s, OpenRISC and a number of others, as they are more or less bound to the forbidden endianness. That would leave the tiny 'endianness' speck of the ordering problem area 'solved' (and a few manufacturers would get rid of some nasty competitors). But the rest of the 'ordering' problem domain would remain unsolved. I understand that you don't care about the rest. That is OK with me, as long as you accept that today is 2/6, 2024.

                    Religious freedom is the freedom to say that two plus two make five.

                    H 1 Reply Last reply
                    0
                    • T trønderen

                      Sure, we could select one tiny little speck of the endianness problem - byte ordering, say - and ignore the rest. Assuming that it was possible to select one single byte ordering and rule out any others, we could declare: 'Hooray! Now the world is free of endianness problems!' Maybe that would be the case inside your little IDE. At least until you have to handle a date. Or an IP address. Or a decimal multi-digit number. You may argue: But those are not endianness problems! They is something different from the ordering of bytes within a word! I'll accept what you say, and you have the full right to say that nothing else than byte ordering falls in under 'endianness'. But the issues are about ordering smallest unit to biggest or biggest to smallest. We could use a different term for this wider problem area, e.g. 'big ordering' or 'small ordering' (and 'mixed ordering'), making 'endianness' a subset of 'ordering'. In principle, we could then throw out all IBMs, Powers, MC68s, OpenRISC and a number of others, as they are more or less bound to the forbidden endianness. That would leave the tiny 'endianness' speck of the ordering problem area 'solved' (and a few manufacturers would get rid of some nasty competitors). But the rest of the 'ordering' problem domain would remain unsolved. I understand that you don't care about the rest. That is OK with me, as long as you accept that today is 2/6, 2024.

                      Religious freedom is the freedom to say that two plus two make five.

                      H Offline
                      H Offline
                      honey the codewitch
                      wrote on last edited by
                      #10

                      trønderen wrote:

                      That is OK with me, as long as you accept that today is 2/6, 2024.

                      Heh. As an American, that actually took some getting used to when I'd date my articles here. We do things differently here. Dumber. See our football. Our "cheese". etc.

                      Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                      1 Reply Last reply
                      0
                      • 1 11917640 Member

                        I like this approach: Let's decide, whether the whole world is little or big endian. Then we can apply this decision in the computer world. By the way, what programming language was used to write the whole world? I think this was C.

                        K Offline
                        K Offline
                        kalberts
                        wrote on last edited by
                        #11

                        As the Universe is still expanding, going from small to big, I think the answer is obvious. At least on the scale of the Universe.

                        1 1 Reply Last reply
                        0
                        • K kalberts

                          As the Universe is still expanding, going from small to big, I think the answer is obvious. At least on the scale of the Universe.

                          1 Offline
                          1 Offline
                          11917640 Member
                          wrote on last edited by
                          #12

                          Honey the codewitch wrote:

                          humans couldn't universally agree on endian order.

                          Now we know why: the endianness of the whole universe is gradually changed from little to big.

                          1 Reply Last reply
                          0
                          • H honey the codewitch

                            Almost all embedded MCUs are little endian. Almost all display controllers that can connect to them are big endian. My graphics library builds pixels in big endian order on little endian machines as a consequence. It's just more efficient. LVGL is another embedded graphics library - one I contribute to - and they removed a feature on version 9+ where you could set it to swap the bytes on a 16 bit color value. This is to compensate for the endian issues. Not swapping during the draw operation means you need to scan and rearrange the transfer buffer before you send it to the display.

                            evoid lcd_flush_display( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map) {
                            size_t count = (area->x2-area->x1+1)*(area->y2-area->y1+1);
                            for(int i = 0;i>8)&0xFF);
                            }
                            esp_lcd_panel_draw_bitmap(lcd_handle,area->x1,area->y1,area->x2+1,area->y2+1,px_map);
                            LV_UNUSED(disp);
                            }

                            This is less efficient. It's also ugly. This is what's for dinner now in LVGL. This is "progress". The worst part is I understand and even sort of agree with why they did it. The issue is multiple displays, and the fact that some displays may not need the swap, perhaps because they're monochrome or something. Previously prior to 8 LVGL simply didn't support that scenario because the swap option was a #define (LVGL is C, not C++) and it applied to all displays as a consequence. But to remove it entirely seems like it was a decision guided by expediency more than anything. It's unfortunate. And all of it reminds me of why I hate the fact that humans couldn't universally agree on endian order.

                            Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                            J Offline
                            J Offline
                            jochance
                            wrote on last edited by
                            #13

                            One little, two little, three little Indians, Six little, five little, four little endians...

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups