# Business Logic — JKKStringUtil.subStringByte() [24 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.common.util.JKKStringUtil` |
| Layer | Utility (Shared/Common Component) |
| Module | `util` (Package: `eo.common.util`) |

## 1. Role

### JKKStringUtil.subStringByte()

This method is a character-encoding-aware string truncation utility used throughout the system to safely shorten text values to a specified byte length. In enterprise billing and telecom operations systems, database fields, API payloads, and display buffers often have fixed byte-width constraints (e.g., VARCHAR(100) in EUC-JP/SJIS encoding). Truncating by character count alone would risk byte overflow and data corruption — this method solves that problem by counting bytes rather than characters. It distinguishes half-width characters (ASCII, backslash, tilde, half-width katakana) that occupy 1 byte from full-width characters (Japanese kana/kanji, full-width Latin/Cyrillic/Greek) that occupy 2 bytes under Shift-JIS/EUC-JP encoding. The method acts as a shared common-component utility, providing a safe truncation primitive that callers across screens, services, and data-handling layers can invoke when they need to enforce byte-length limits on arbitrary strings. If the input string is shorter than the requested byte length, the original string is returned unchanged — no unnecessary copy is made.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["subStringByte(String str, int len)"])
    STEP1["dstlen = 0;"]
    LOOP["for i = 0 to str.length() - 1"]
    CHAR["c = str.charAt(i)"]
    COND["c <= 0x007E or c == 0x00A5 or c == 0x203E or (c >= 0xFF61 and c <= 0xFF9F)"]
    BYTE1["dstlen += 1 (half-width: 1 byte)"]
    BYTE2["dstlen += 2 (full-width: 2 bytes)"]
    CHECK["dstlen > len"]
    TRUNCATE["return str.substring(0, i)"]
    NEXT["i++ (next iteration)"]
    END_RETURN["return str (original string)"]

    START --> STEP1
    STEP1 --> LOOP
    LOOP --> CHAR
    CHAR --> COND
    COND -->|"Yes"| BYTE1
    COND -->|"No"| BYTE2
    BYTE1 --> CHECK
    BYTE2 --> CHECK
    CHECK -->|"Yes"| TRUNCATE
    CHECK -->|"No"| NEXT
    NEXT --> LOOP
    LOOP -->|"i == str.length"| END_RETURN
```

The method iterates over each character of the input string, counting its byte footprint under Shift-JIS/EUC-JP encoding: half-width characters (ASCII range, backslash `\`, tilde `~`, half-width katakana U+FF61–U+FF9F) count as 1 byte; all other characters (full-width) count as 2 bytes. Once the accumulated byte count exceeds the requested length, the method returns the substring up to the character *before* the overflow point. If the loop completes without exceeding the byte limit, the original string is returned as-is.

**Important note on truncation precision:** When a full-width character would exceed the byte limit, this method truncates *before* that character (at position `i`), meaning it never produces a partial multi-byte character. The last included character is always the one whose byte contribution was within the limit, and `substring(0, i)` returns the string exclusive of index `i` — the problematic character is excluded.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `str` | `String` | The input string to be truncated. Represents arbitrary text content — typically a field value, name, address, or description that must fit within a fixed byte-width buffer (e.g., a 50-byte database column or display area). |
| 2 | `len` | `int` | The target maximum byte length. This is a byte-count constraint, not a character count. For example, `len = 50` means the output must be at most 50 bytes under Shift-JIS/EUC-JP encoding. Must be a non-negative integer; the method does not validate negative inputs. |

No instance fields or external state are read by this method — it is a pure, stateless function.

## 4. CRUD Operations / Called Services

This method performs no database operations, no service calls, and no CRUD actions. It is a pure string transformation utility with zero external dependencies.

## 5. Dependency Trace

No callers were found in the codebase. This method is defined as `public static` in a shared utility class, indicating it is intended for use by other components — but no current usage was detected. It may be called by compiled-and-deployed modules not present in the scanned source tree, or its callers may have been removed during refactoring.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| No callers found | — | — | — |

## 6. Per-Branch Detail Blocks

**Block 1** — INIT (L115)

Initialize the byte accumulator before iterating over the string.

| # | Type | Code |
|---|------|------|
| 1 | SET | `dstlen = 0;` // Initialize byte-length counter to zero |
| 2 | SET | `i = 0;` // Loop index for character iteration |

**Block 2** — FOR (L116) (L116-L120)

Iterate over each character of the input string, counting its byte footprint.

| # | Type | Code |
|---|------|------|
| 1 | SET | `c = str.charAt(i);` // Extract character at position i // (英数: alphanumeric / char at index) |

**Block 2.1** — IF (L117-L121) — Condition: `c <= '~' || c == '¥' || c == '‾' || (c >= '｡' && c <= 'ﾟ')`

Determine whether the current character is half-width (1-byte) or full-width (2-byte).

**Block 2.1.1** — IF-THEN (L117-L121) — Half-width character match `[c <= '~' = 0x007E]` `[c == '¥' = 0x00A5]` `[c == '‾' = 0x203E]` `[c >= '｡' and c <= 'ﾟ']`
A half-width character: ASCII printable range (U+0000–U+007E), backslash (U+00A5), tilde (U+203E), or half-width katakana range (U+FF61–U+FF9F). Under Shift-JIS/EUC-JP encoding, these characters occupy exactly 1 byte.

| # | Type | Code |
|---|------|------|
| 1 | SET | `dstlen += 1;` // Increment byte counter by 1 // (英数: half-width alphanumeric counts as 1 byte) |

**Block 2.1.2** — ELSE (L122-L124) — Full-width character
Any character outside the half-width range (e.g., Japanese kana, kanji, full-width Latin/Cyrillic/Greek). These occupy 2 bytes under Shift-JIS/EUC-JP encoding.

| # | Type | Code |
|---|------|------|
| 1 | SET | `dstlen += 2;` // Increment byte counter by 2 // (全角: full-width characters count as 2 bytes) |

**Block 2.2** — IF (L125-L128) (L125-L128) — Condition: `dstlen > len`

After counting the current character's bytes, check if the accumulator now exceeds the requested byte limit.

**Block 2.2.1** — IF-THEN (L125-L128) — `dstlen > len` is true
The accumulated byte count has exceeded the target. Truncate the string to exclude the character that caused the overflow.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return str.substring(0, i);` // Return string truncated before the overflow character |

**Block 2.2.2** — IF-ELSE — `dstlen > len` is false
The byte count is still within the limit. Continue iterating to the next character.

| # | Type | Code |
|---|------|------|
| 1 | (implicit) | Loop advances: `i++` — proceed to next character |

**Block 3** — RETURN (L130) (L130)

Loop completed without exceeding the byte limit. The entire string fits within `len` bytes — return it unchanged.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return str;` // Return original string as-is // (指定長 > 文字列長の場合は文字列をそのまま返却: if specified length > string length, return the string as-is) |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `str` | Parameter | Input string to be truncated to a byte length |
| `len` | Parameter | Target maximum byte length (not character count) |
| `dstlen` | Local variable | Running byte-length accumulator — tracks total bytes consumed so far |
| Half-width character | Concept | A character that occupies 1 byte under Shift-JIS/EUC-JP encoding (ASCII range, backslash, tilde, half-width katakana) |
| Full-width character | Concept | A character that occupies 2 bytes under Shift-JIS/EUC-JP encoding (Japanese kana, kanji, full-width symbols) |
| U+007E | Unicode | Highest codepoint for ASCII printable characters — used as the half-width upper bound |
| U+00A5 | Unicode | Backslash character `\` — treated as half-width (1 byte) in Shift-JIS |
| U+203E | Unicode | Overline character `‾` — treated as half-width (1 byte) |
| U+FF61–U+FF9F | Unicode Range | Half-width katakana character range — all treated as 1-byte characters |
| `substring(0, i)` | API call | Java method returning characters from index 0 up to (but not including) index `i` |
